///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Область ПрограммныйИнтерфейс

#Область КонтейнерЗначенияДляХраненияНаФорме

#Область ХранилищеКонтейнераИзЗначения

// Значение хранилища контейнера граница.
// 
// Параметры:
//  Граница -  Граница
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаГраница
Функция ЗначениеХранилищаКонтейнераГраница(Граница) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаГраница();
	Хранилище.Дата = Граница.Значение;
	Если Граница.ВидГраницы = ВидГраницы.Включая Тогда
		Хранилище.ВидГраницы = "Включая";
	Иначе
		Хранилище.ВидГраницы = "Исключая";
	КонецЕсли;

	Возврат Хранилище;
КонецФункции


// Значение хранилища контейнера момента времени.
// 
// Параметры:
//  Момент - МоментВремени
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМоментВремени
Функция ЗначениеХранилищаКонтейнераМоментаВремени(Момент) Экспорт
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ЗначениеХранилищаКонтейнераМоментаВремениПоДатеИСсылке(Момент.Дата,
																								   Момент.Ссылка);
КонецФункции

// Значение хранилища контейнера таблицы значений.
// 
// Параметры:
//  ТаблицаЗначений - ТаблицаЗначений -  Таблица значений
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТаблицыЗначений
Функция ЗначениеХранилищаКонтейнераТаблицыЗначений(ТаблицаЗначений) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТаблицыЗначений();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(ТаблицаЗначений);
	Хранилище.КоличествоСтрок = ТаблицаЗначений.Количество();
	Хранилище.КоличествоКолонок = ТаблицаЗначений.Колонки.Количество();
	
	Возврат Хранилище;
КонецФункции

// Хначение хранилища контейнера дерева значений.
// 
// Параметры:
//  ДеревоЗначений -ДеревоЗначений-Дерево значений
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияДереваЗначений
Функция ЗначениеХранилищаКонтейнераДереваЗначений(ДеревоЗначений) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТаблицыЗначений();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(ДеревоЗначений);
	Хранилище.КоличествоСтрок = ДеревоЗначений.Строки.Количество();
	Хранилище.КоличествоКолонок = ДеревоЗначений.Колонки.Количество();
	
	Возврат Хранилище;
КонецФункции

// Значение хранилища контейнера типа.
// 
// Параметры:
//  Тип - Тип
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа
Функция ЗначениеХранилищаКонтейнераТипа(Тип) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(Тип);
	Хранилище.Имя = Строка(Тип);
	
	Возврат Хранилище;	
КонецФункции

// Значение хранилища контейнера описание типов.
// 
// Параметры:
//  ОписаниеТипов - ОписаниеТипов
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа 
Функция ЗначениеХранилищаКонтейнераОписаниеТипов(ОписаниеТипов) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа();
	Хранилище.Значение = ЗначениеВСтрокуXML(ОписаниеТипов);
	Хранилище.Имя = Строка(ОписаниеТипов);
	
	Возврат Хранилище;	
	
КонецФункции

// Значение хранилище контейнера структуры.
// 
// Параметры:
//  ЗначениеСтруктуры - Структура -  Значение структуры
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСтруктура
Функция ЗначениеХранилищеКонтейнераСтруктуры(ЗначениеСтруктуры) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСтруктура();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(ЗначениеСтруктуры);
	Хранилище.КоличествоКлючей= ЗначениеСтруктуры.Количество();
	
	Ключи = Новый Массив;
	Для Каждого КлючЗначение ИЗ ЗначениеСтруктуры Цикл
		Ключи.Добавить(КлючЗначение.Ключ);	
	КонецЦикла;
	Хранилище.Ключи = СтрСоединить(Ключи, ",");
	
	Возврат Хранилище;	
	
КонецФункции

// Значение хранилище контейнера структуры.
// 
// Параметры:
//  ЗначениеСтруктуры - ФиксированнаяСтруктура -  Значение структуры
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСтруктура
Функция ЗначениеХранилищеКонтейнераФисированнойСтруктуры(ЗначениеСтруктуры) Экспорт
	Возврат ЗначениеХранилищеКонтейнераСтруктуры(Новый Структура(ЗначениеСтруктуры));
КонецФункции

// Значение хранилище контейнера соответствия.
// 
// Параметры:
//  ЗначениеСоответствие - Соответствие из КлючИЗначение
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСоответствие
Функция ЗначениеХранилищеКонтейнераСоответствия(ЗначениеСоответствие) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСоответствие();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(ЗначениеСоответствие);
	Хранилище.КоличествоКлючей= ЗначениеСоответствие.Количество();
	
	Возврат Хранилище;	
	
КонецФункции

// Значение хранилище контейнера соответствия.
// 
// Параметры:
//  ЗначениеСоответствие - ФиксированноеСоответствие из КлючИЗначение
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСоответствие
Функция ЗначениеХранилищеКонтейнераФиксированногоСоответствия(ЗначениеСоответствие) Экспорт
	Возврат ЗначениеХранилищеКонтейнераСоответствия(Новый Соответствие(ЗначениеСоответствие));
КонецФункции

// Значение хранилища контейнера хранилища значения.
// 
// Параметры:
//  ХранилищеЗначения -ХранилищеЗначения-Хранилище значения
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаХранилищеЗначения
Функция ЗначениеХранилищаКонтейнераХранилищаЗначения(ХранилищеЗначения) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаХранилищеЗначения();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(ХранилищеЗначения);
	
	ЗначениеХранилища = ХранилищеЗначения.Получить();
	Хранилище.Тип= Строка(ТипЗнч(ЗначениеХранилища));
	
	Возврат Хранилище;	
	
КонецФункции

// Значение хранилища контейнера хранилища значения.
// 
// Параметры:
//  Значение -Произвольный-Хранилище значения
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаХранилищеЗначения
Функция ЗначениеХранилищаКонтейнераХранилищаЗначенияИзПроизвользоногоЗначения(Значение) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаХранилищеЗначения();
	Хранилище.Тип= Строка(ТипЗнч(Значение));
	Хранилище.Значение = ЗначениеВСтрокуВнутр(Новый ХранилищеЗначения(Значение, Новый СжатиеДанных(9)));

	Возврат Хранилище;	
	
КонецФункции

// Значение хранилища контейнера списка значений.
// 
// Параметры:
//  Список - СписокЗначений из Произвольный
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСписокЗначений
Функция ЗначениеХранилищаКонтейнераСпискаЗначений(Список) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСписокЗначений();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(Список);
	Хранилище.Представление = Строка(Список);
	
	Возврат Хранилище;
КонецФункции

// Значение хранилища контейнера массива.
// 
// Параметры:
//  Массив -  Массив из Произвольный
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМассив
Функция ЗначениеХранилищаКонтейнераМассива(Массив) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСписокЗначений();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(Массив);
	
	Список = Новый СписокЗначений();
	Список.ЗагрузитьЗначения(Массив);
	Хранилище.Представление = Строка(Список);
	
	Возврат Хранилище;
КонецФункции

// Значение хранилища контейнера массива.
// 
// Параметры:
//  Массив -  ФиксированныйМассив из Произвольный
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМассив
Функция ЗначениеХранилищаКонтейнераФиксированногоМассива(Массив) Экспорт
	Возврат ЗначениеХранилищаКонтейнераМассива(Новый Массив(Массив));
КонецФункции

// Значение хранилища контейнера массива.
// 
// Параметры:
//  Список -  СписокЗначений из Произвольный
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМассив
Функция ЗначениеХранилищаКонтейнераМассиваИзСпискаЗначений(Список) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСписокЗначений();
	Хранилище.Значение = ЗначениеВСтрокуВнутр(Список.ВыгрузитьЗначения());
	Хранилище.Представление = Строка(Список);
	
	Возврат Хранилище;
КонецФункции

// Значение хранилища контейнера двочных данных.
// 
// Параметры:
//  ДвоичныеДанные - ДвоичныеДанные- Двоичные данные
// 
// Возвращаемое значение:
//  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаДвоичныеДанные
Функция ЗначениеХранилищаКонтейнераДвочныхДанных(ДвоичныеДанные) Экспорт
	Хранилище = УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаДвоичныеДанные();
	Хранилище.Значение = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
	Хранилище.Размер= ДвоичныеДанные.Размер();
	Хранилище.Представление = Лев(Строка(ДвоичныеДанные), 300);
	
	Возврат Хранилище;
	
КонецФункции

#КонецОбласти

#Область ЗначениеИзХранилищаКонтейнера

// Значение из хранилища контейнера момента времени.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМоментВремени 
// 
// Возвращаемое значение:
//  МоментВремени -  Значение из хранилища контейнера момента времени
Функция ЗначениеИзХранилищаКонтейнераМоментаВремени(Хранилище) Экспорт
	Возврат Новый МоментВремени(Хранилище.Дата, Хранилище.Ссылка);
КонецФункции

// Значение из хранилища контейнера граница.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаГраница 
// 
// Возвращаемое значение:
//  Граница -  Значение из хранилища контейнера граница
Функция ЗначениеИзХранилищаКонтейнераГраница(Хранилище) Экспорт
	Возврат Новый Граница(Хранилище.Дата, ВидГраницы[Хранилище.ВидГраницы]);
КонецФункции

// Значение из хранилища контейнера таблицы значений.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТаблицыЗначений
// 
// Возвращаемое значение:
//  ТаблицаЗначений, Неопределено -  Значение из хранилища контейнера таблицы значений
Функция ЗначениеИзХранилищаКонтейнераТаблицыЗначений(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера дерева значений.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияДереваЗначений
// 
// Возвращаемое значение:
//  ДеревоЗначений, Неопределено -  Значение из хранилища контейнера дерева значений
Функция ЗначениеИзХранилищаКонтейнераДереваЗначений(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера тип.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа
// 
// Возвращаемое значение:
//  Тип, Неопределено -  Значение из хранилища контейнера тип
Функция ЗначениеИзХранилищаКонтейнераТип(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера описания типов.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипа
// 
// Возвращаемое значение:
//  ОписаниеТипов, Неопределено -  Значение из хранилища контейнера описания типов
Функция ЗначениеИзХранилищаКонтейнераОписанияТипов(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиXML(Хранилище.Значение, Тип("ОписаниеТипов"));
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера структуры.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСтруктура
// 
// Возвращаемое значение:
//  Структура, Неопределено -  Значение из хранилища контейнера структуры
Функция ЗначениеИзХранилищаКонтейнераСтруктуры(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера структуры.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСтруктура
// 
// Возвращаемое значение:
//  ФиксированнаяСтруктура, Неопределено -  Значение из хранилища контейнера структуры
Функция ЗначениеИзХранилищаКонтейнераФиксированнойСтруктуры(Хранилище) Экспорт
	Структура = ЗначениеИзХранилищаКонтейнераСтруктуры(Хранилище);
	
	Если Структура = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Новый ФиксированнаяСтруктура(Структура);
КонецФункции

// Значение из хранилища контейнера соответствия.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСоответствие
// 
// Возвращаемое значение:
//  Соответствие из КлючИЗначение, Неопределено -  Значение из хранилища контейнера соответствия
Функция ЗначениеИзХранилищаКонтейнераСоответствия(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера соответствия.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСоответствие
// 
// Возвращаемое значение:
//  ФиксированноеСоответствие из КлючИЗначение, Неопределено -  Значение из хранилища контейнера соответствия
Функция ЗначениеИзХранилищаКонтейнераФиксированногоСоответствия(Хранилище) Экспорт
	Соответствие = ЗначениеИзХранилищаКонтейнераСоответствия(Хранилище);
	Если Соответствие = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Новый ФиксированноеСоответствие(Соответствие);
КонецФункции


// Значение из хранилища контейнера хранилища значения.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаХранилищеЗначения
// 
// Возвращаемое значение:
//  ХранилищеЗначения, Неопределено -  Значение из хранилища контейнера хранилища значения
Функция ЗначениеИзХранилищаКонтейнераХранилищаЗначения(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера списка значения.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаСписокЗначений
// 
// Возвращаемое значение:
//  СписокЗначений из Произвольный, Неопределено -  Значение из хранилища контейнера списка значения
Функция ЗначениеИзХранилищаКонтейнераСпискаЗначения(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера массива.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМассив 
// 
// Возвращаемое значение:
//  Массив из Произвольный, Неопределено -  Значение из хранилища контейнера массива
Функция ЗначениеИзХранилищаКонтейнераМассива(Хранилище) Экспорт
	Попытка
		Возврат ЗначениеИзСтрокиВнутр(Хранилище.Значение);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Значение из хранилища контейнера массива.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаМассив 
// 
// Возвращаемое значение:
//  ФиксированныйМассив из Произвольный, Неопределено -  Значение из хранилища контейнера массива
Функция ЗначениеИзХранилищаКонтейнераФиксированногоМассива(Хранилище) Экспорт
	Массив = ЗначениеИзХранилищаКонтейнераМассива(Хранилище);
	Если Массив = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Новый ФиксированныйМассив(Массив);
КонецФункции

// Значение из хранилища контейнера двоичных данных.
// 
// Параметры:
//  Хранилище - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйХранилищеЗначенияТипаДвоичныеДанные
// 
// Возвращаемое значение:
//  Неопределено -  Значение из хранилища контейнера двоичных данных
Функция ЗначениеИзХранилищаКонтейнераДвоичныхДанных(Хранилище) Экспорт
	Если Хранилище.Значение = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Хранилище.Значение.Получить();

КонецФункции

#КонецОбласти

// Значение в контейнер для формы.
// 
// Параметры:
//  Значение - Произвольный - Значение
// 
// Возвращаемое значение:
//  Структура -  см. УИ_ОбщегоНазначенияКлиентСервер.НовыйКонтейнерЗначения
// Возвращаемое значение: 
//  Произвольный - Если тип не поддерживается контейнером, то возращается само значение
Функция ЗначениеВКонтейнерДляФормы(Значение) Экспорт
	ТипыКонтейнеров = УИ_ОбщегоНазначенияКлиентСервер.ТипыКонтейнеровЗначения();
	
	НовыйКонтейнер = УИ_ОбщегоНазначенияКлиентСервер.НовыйКонтейнерЗначенияПоТипу(ТипЗнч(Значение));
	
	Если НовыйКонтейнер.Тип = ТипыКонтейнеров.Граница Тогда
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераГраница(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.МоментВремени Тогда
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераМоментаВремени(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ТаблицаЗначений Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераТаблицыЗначений(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.Тип Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераТипа(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ОписаниеТипов Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераОписаниеТипов(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.Структура Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищеКонтейнераСтруктуры(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ФиксированнаяСтруктура Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищеКонтейнераФисированнойСтруктуры(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.Соответствие Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищеКонтейнераСоответствия(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ФиксированноеСоответствие Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищеКонтейнераФиксированногоСоответствия(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ДеревоЗначений Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераДереваЗначений(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ТабличныйДокумент Тогда 
		НовыйКонтейнер.Хранилище = УИ_ОбщегоНазначенияКлиентСервер.ЗначениеХранилищеКонтейнераТабличногоДокумента(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ХранилищеЗначения Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераХранилищаЗначения(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.СписокЗначений Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераСпискаЗначений(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.Массив Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераМассива(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ФиксированныйМассив Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераФиксированногоМассива(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.Картинка Тогда 
		НовыйКонтейнер.Хранилище = УИ_ОбщегоНазначенияКлиентСервер.ЗначениеХранилищаКонтейнераКартинки(Значение);
	ИначеЕсли НовыйКонтейнер.Тип = ТипыКонтейнеров.ДвоичныеДанные Тогда 
		НовыйКонтейнер.Хранилище = ЗначениеХранилищаКонтейнераДвочныхДанных(Значение);
	Иначе
		Возврат Значение;
	КонецЕсли;	
	УИ_ОбщегоНазначенияКлиентСервер.УстановитьПредставлениеКонтейнера(НовыйКонтейнер);
	
	Возврат НовыйКонтейнер;	
КонецФункции

// Значение из контейнера формы.
// 
// Параметры:
//  Контейнер - см. УИ_ОбщегоНазначенияКлиентСервер.НовыйКонтейнерЗначения
// 
// Возвращаемое значение:
//  Произвольный - Значение, сохраненное в контейнере
Функция ЗначениеИзКонтейнераФормы(Контейнер) Экспорт
	ТипыКонтейнеров = УИ_ОбщегоНазначенияКлиентСервер.ТипыКонтейнеровЗначения();
	
	Если Контейнер.Тип = ТипыКонтейнеров.Граница Тогда
		Возврат ЗначениеИзХранилищаКонтейнераГраница(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.МоментВремени Тогда
		Возврат ЗначениеИзХранилищаКонтейнераМоментаВремени(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ТаблицаЗначений Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераТаблицыЗначений(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ДеревоЗначений Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераДереваЗначений(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.Тип Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераТип(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ОписаниеТипов Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераОписанияТипов(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.Структура Тогда 	
		Возврат ЗначениеИзХранилищаКонтейнераСтруктуры(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ФиксированнаяСтруктура Тогда 	
		Возврат ЗначениеИзХранилищаКонтейнераФиксированнойСтруктуры(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.Соответствие Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераСоответствия(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ФиксированноеСоответствие Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераФиксированногоСоответствия(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ТабличныйДокумент Тогда 
		Возврат УИ_ОбщегоНазначенияКлиентСервер.ЗначениеИзХранилищаКонтейнераТабличногоДокумента(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ХранилищеЗначения Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераХранилищаЗначения(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.СписокЗначений Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераСпискаЗначения(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.Массив Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераМассива(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ФиксированныйМассив Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераФиксированногоМассива(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.Картинка Тогда 
		Возврат УИ_ОбщегоНазначенияКлиентСервер.ЗначениеИзХранилищаКонтейнераКартинки(Контейнер.Хранилище);
	ИначеЕсли Контейнер.Тип = ТипыКонтейнеров.ДвоичныеДанные Тогда 
		Возврат ЗначениеИзХранилищаКонтейнераДвоичныхДанных(Контейнер.Хранилище);
	КонецЕсли;

	Возврат Неопределено;
КонецФункции


#КонецОбласти

// Возвращает признак работы в режиме разделения данных по областям
// (технически это признак условного разделения).
// 
// Возвращает Ложь, если конфигурация не может работать в режиме разделения данных
// (не содержит общих реквизитов, предназначенных для разделения данных).
//
// Возвращаемое значение:
//  Булево - Истина, если разделение включено.
//         - Ложь,   если разделение выключено или не поддерживается.
//
//@skip-check doc-comment-type
Функция РазделениеВключено() Экспорт

	//Если ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса") Тогда
	//	МодульРаботаВМоделиСервиса = ОбщийМодуль("РаботаВМоделиСервиса");
	//	Возврат МодульРаботаВМоделиСервиса.РазделениеВключено();
	//Иначе
		Возврат Ложь;
	//КонецЕсли;

КонецФункции

// Возвращает Истина, если "функциональная" подсистема существует в конфигурации.
// Предназначена для реализации вызова необязательной подсистемы (условного вызова).
//
// У "функциональной" подсистемы снят флажок "Включать в командный интерфейс".
//
// Параметры:
//  ПолноеИмяПодсистемы - Строка - полное имя объекта метаданных подсистема
//                        без слов "Подсистема." и с учетом регистра символов.
//                        Например: "СтандартныеПодсистемы.ВариантыОтчетов".
//
// Пример:
//  Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ВариантыОтчетов") Тогда
//  	МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
//  	МодульВариантыОтчетов.<Имя метода>();
//  КонецЕсли;
//
// Возвращаемое значение:
//  Булево - Истина, если существует.
//
Функция ПодсистемаСуществует(ПолноеИмяПодсистемы) Экспорт

	ИменаПодсистем = УИ_ОбщегоНазначенияПовтИсп.ИменаПодсистем();
	Возврат ИменаПодсистем.Получить(ПолноеИмяПодсистемы) <> Неопределено;

КонецФункции

// Возвращает ссылку на общий модуль по имени.
//
// Параметры:
//  Имя          - Строка - имя общего модуля, например:
//                 "ОбщегоНазначения",
//                 "ОбщегоНазначенияКлиент".
//
// Возвращаемое значение:
//  ОбщийМодуль - общий модуль.
//
Функция ОбщийМодуль(Имя) Экспорт

	Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда
		//@skip-check server-execution-safe-mode
		Модуль = Вычислить(Имя); // ВычислитьВБезопасномРежиме не требуется, т.к. проверка надежная.
	ИначеЕсли СтрЧислоВхождений(Имя, ".") = 1 Тогда
		Возврат СерверныйМодульМенеджера(Имя);
	Иначе
		Модуль = Неопределено;
	КонецЕсли;
	
//	Если ТипЗнч(Модуль) <> Тип("ОбщийМодуль") Тогда
//		ВызватьИсключение СтрШаблон(НСтр("ru = 'Общий модуль ""%1"" не найден.'"), Имя);
//	КонецЕсли;

	Возврат Модуль;

КонецФункции

// Возвращает признак возможности обращения к разделенным данным (которые входят в состав разделителей).
// Признак относится к сеансу, но может меняться во время работы сеанса, если разделение было включено
// в самом сеансе, поэтому проверку следует делать непосредственно перед обращением к разделенным данным.
// 
// Возвращает Истина, если конфигурация не может работать в режиме разделения данных
// (не содержит общих реквизитов, предназначенных для разделения данных).
//
// Возвращаемое значение:
//   Булево - Истина, если разделение не поддерживается, либо разделение выключено,
//                    либо разделение включено и разделители    установлены.
//          - Ложь,   если разделение включено и разделители не установлены.
//
Функция ДоступноИспользованиеРазделенныхДанных() Экспорт

	//Если ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса") Тогда
	//	МодульРаботаВМоделиСервиса = ОбщийМодуль("РаботаВМоделиСервиса");
	//	Возврат МодульРаботаВМоделиСервиса.ДоступноИспользованиеРазделенныхДанных();
	//Иначе
		Возврат Истина;
	//КонецЕсли;

КонецФункции

// Определяет, что эта информационная база является подчиненным узлом
// распределенной информационной базы (РИБ).
//
// Возвращаемое значение: 
//  Булево - Истина, если эта информационная база является подчиненным узлом РИБ.
//
Функция ЭтоПодчиненныйУзелРИБ() Экспорт

	УстановитьПривилегированныйРежим(Истина);

	Возврат ПланыОбмена.ГлавныйУзел() <> Неопределено;

КонецФункции

// Преобразует (сериализует) любое значение в XML-строку.
// Преобразованы в могут быть только те объекты, для которых в синтакс-помощнике указано, что они сериализуются.
// См. также ЗначениеИзСтрокиXML.
//
// Параметры:
//  Значение - Произвольный - значение, которое необходимо сериализовать в XML-строку.
//
// Возвращаемое значение:
//  Строка - XML-строка.
//
Функция ЗначениеВСтрокуXML(Значение) Экспорт

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, НазначениеТипаXML.Явное);

	Возврат ЗаписьXML.Закрыть();
КонецФункции

// Выполняет преобразование (десериализацию) XML-строки в значение.
// См. также ЗначениеВСтрокуXML.
//
// Параметры:
//  СтрокаXML - Строка - XML-строка, с сериализованным объектом..
//
// Возвращаемое значение:
//  Произвольный - значение, полученное из переданной XML-строки.
//
Функция ЗначениеИзСтрокиXML(СтрокаXML, Тип = Неопределено) Экспорт

	ЧтениеXML = Новый ЧтениеXML;
	ЧтениеXML.УстановитьСтроку(СтрокаXML);

	Если Тип = Неопределено Тогда
		Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
	Иначе
		Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML, Тип);
	КонецЕсли;
КонецФункции


// Определяет режим эксплуатации информационной базы файловый (Истина) или серверный (Ложь).
// При проверке используется СтрокаСоединенияИнформационнойБазы, которую можно указать явно.
//
// Параметры:
//  СтрокаСоединенияИнформационнойБазы - Строка - параметр используется, если
//                 нужно проверить строку соединения не текущей информационной базы.
//
// Возвращаемое значение:
//  Булево - Истина, если файловая.
//
Функция ИнформационнаяБазаФайловая(Знач СтрокаСоединенияИнформационнойБазы = "") Экспорт

	Если ПустаяСтрока(СтрокаСоединенияИнформационнойБазы) Тогда
		СтрокаСоединенияИнформационнойБазы =  СтрокаСоединенияИнформационнойБазы();
	КонецЕсли;
	Возврат СтрНайти(ВРег(СтрокаСоединенияИнформационнойБазы), "FILE=") = 1;

КонецФункции 

Процедура УстановитьБезопасныйРежимБСП()
//	Если ПодсистемаСуществует("СтандартныеПодсистемы.ПрофилиБезопасности") Тогда
//		МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
//		Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности()
//			И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда
//
//			МодульРаботаВБезопасномРежиме = ОбщийМодуль("РаботаВБезопасномРежиме");
//			ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы();
//
//			Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда
//
//				УстановитьБезопасныйРежим(ПрофильИнформационнойБазы);
//				Если БезопасныйРежим() = Истина Тогда
//					УстановитьБезопасныйРежим(Ложь);
//				КонецЕсли;
//
//			КонецЕсли;
//
//		КонецЕсли;
//	КонецЕсли;
КонецПроцедуры

// Выполнить экспортную процедуру объекта встроенного языка по имени.
// При включении профилей безопасности для вызова оператора Выполнить() используется
// переход в безопасный режим с профилем безопасности, используемом для информационной базы
// (если выше по стеку не был установлен другой безопасный режим).
//
// Параметры:
//  Объект    - Произвольный - объект встроенного языка 1С:Предприятия, содержащий методы (например, ОбработкаОбъект).
//  ИмяМетода - Строка       - имя экспортной процедуры модуля объекта обработки.
//  Параметры - Массив       - параметры передаются в процедуру <ИмяПроцедуры>
//                             в порядке расположения элементов массива.
//
Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт
	
	// Проверка имени метода на корректность.
	Попытка
		//@skip-warning
		Тест = Новый Структура(ИмяМетода, ИмяМетода);
	Исключение
		ВызватьИсключение СтрШаблон(
			НСтр("ru='Некорректное значение параметра ИмяМетода (%1) в ОбщегоНазначения.ВыполнитьМетодОбъекта'"),
			ИмяМетода);
	КонецПопытки;
	
	Попытка
		УстановитьБезопасныйРежимБСП();
	Исключение
	КонецПопытки;

	ПараметрыСтрока = "";
	Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда
		Для Индекс = 0 По Параметры.ВГраница() Цикл
			ПараметрыСтрока = ПараметрыСтрока + "Параметры[" + Индекс + "],";
		КонецЦикла;
		ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1);
	КонецЕсли;

	//@skip-check server-execution-safe-mode
	Выполнить "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";

КонецПроцедуры


// Выполнить экспортную процедуру по имени с уровнем привилегий конфигурации.
// При включении профилей безопасности для вызова оператора Выполнить() используется
// переход в безопасный режим с профилем безопасности, используемом для информационной базы
// (если выше по стеку не был установлен другой безопасный режим).
//
// Параметры:
//  ИмяМетода  - Строка - имя экспортной процедуры в формате
//                       <имя объекта>.<имя процедуры>, где <имя объекта> - это
//                       общий модуль или модуль менеджера объекта.
//  Параметры  - Массив - параметры передаются в процедуру <ИмяЭкспортнойПроцедуры>
//                        в порядке расположения элементов массива.
// 
// Пример:
//  Параметры = Новый Массив();
//  Параметры.Добавить("1");
//  ОбщегоНазначения.ВыполнитьМетодКонфигурации("МойОбщийМодуль.МояПроцедура", Параметры);
//
Процедура ВыполнитьМетодКонфигурации(Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт

	ПроверитьИмяПроцедурыКонфигурации(ИмяМетода);

	Попытка
		УстановитьБезопасныйРежимБСП();
	Исключение
		
	КонецПопытки;

	ПараметрыСтрока = "";
	Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда
		Для Индекс = 0 По Параметры.ВГраница() Цикл
			ПараметрыСтрока = ПараметрыСтрока + "Параметры[" + Индекс + "],";
		КонецЦикла;
		ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1);
	КонецЕсли;

	Выполнить ИмяМетода + "(" + ПараметрыСтрока + ")";

КонецПроцедуры

// Выполняет произвольный алгоритм на встроенном языке 1С:Предприятия, предварительно устанавливая
// безопасный режим выполнения кода и безопасный режим разделения данных для всех разделителей,
// присутствующих в составе конфигурации.
//
// Параметры:
//  Алгоритм  - Строка - алгоритм на встроенном языке "1С:Предприятия".
//  Параметры - Произвольный -  контекст, который требуется для выполнения алгоритма.
//    В тексте алгоритма обращение к контексту должно происходить по имени "Параметры".
//    Например, выражение "Параметры.Значение1 = Параметры.Значение2" обращается к значениям
//    "Значение1" и "Значение2", переданным в Параметры, как свойства.
//
// Пример:
//
//  Параметры = Новый Структура;
//  Параметры.Вставить("Значение1", 1);
//  Параметры.Вставить("Значение2", 10);
//  ОбщегоНазначения.ВыполнитьВБезопасномРежиме("Параметры.Значение1 = Параметры.Значение2", Параметры);
//
Процедура ВыполнитьВБезопасномРежиме(Знач Алгоритм, Знач Параметры = Неопределено) Экспорт
	
	УстановитьБезопасныйРежим(Истина);
	
//	Если ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
//		МодульРаботаВМоделиСервиса = ОбщийМодуль("РаботаВМоделиСервиса");
//		МассивРазделителей = МодульРаботаВМоделиСервиса.РазделителиКонфигурации();
//	Иначе
		МассивРазделителей = Новый Массив;
//	КонецЕсли;
	
	Для Каждого ИмяРазделителя Из МассивРазделителей Цикл
		
		УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		
	КонецЦикла;
	
	Выполнить Алгоритм;
	
КонецПроцедуры

// Вычисляет переданное выражение, предварительно устанавливая безопасный режим выполнения кода
// и безопасный режим разделения данных для всех разделителей, присутствующих в составе конфигурации.
//
// Параметры:
//  Выражение - Строка - выражение на встроенном языке 1С:Предприятия.
//  ПараметрыМетода - Произвольный - контекст, который требуется для вычисления выражения.
//    В тексте выражения обращение к контексту должно происходить по имени "Параметры".
//    Например, выражение "Параметры.Значение1 = Параметры.Значение2" обращается к значениям
//    "Значение1" и "Значение2" переданные в Параметры, как свойства.
//
// Возвращаемое значение:
//   Произвольный - результат вычисления выражения.
//
// Пример:
//
//  // Пример 1
//  Параметры = Новый Структура;
//  Параметры.Вставить("Значение1", 1);
//  Параметры.Вставить("Значение2", 10);
//  Результат = ОбщегоНазначения.ВычислитьВБезопасномРежиме("Параметры.Значение1 = Параметры.Значение2", Параметры);
//
//  // Пример 2
//  Результат = ОбщегоНазначения.ВычислитьВБезопасномРежиме("СтандартныеПодсистемыСервер.ВерсияБиблиотеки()");
//
Функция ВычислитьВБезопасномРежиме(Знач Выражение, Знач ПараметрыМетода = Неопределено) Экспорт
	
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ВычислитьВБезопасномРежиме(Выражение, ПараметрыМетода);
	
КонецФункции


// Проверяет, что переданное имя ИмяПроцедуры является именем экспортной процедуры конфигурации.
// Может использоваться для проверки, что переданная строка не содержит произвольного алгоритма
// на встроенном языке 1С:Предприятия перед использованием его в операторах Выполнить и Вычислить
// при их использовании для динамического вызова методов код конфигурации.
//
// В случае если переданная строка не является именем процедуры конфигурации, генерируется исключение.
//
// Предназначена для вызова из см. процедуру ВыполнитьМетодКонфигурации.
//
// Параметры:
//   ИмяПроцедуры - Строка - проверяемое имя экспортной процедуры.
//
Процедура ПроверитьИмяПроцедурыКонфигурации(Знач ИмяПроцедуры)

	ЧастиИмени = СтрРазделить(ИмяПроцедуры, ".");
	Если ЧастиИмени.Количество() <> 2 И ЧастиИмени.Количество() <> 3 Тогда
		ВызватьИсключение СтрШаблон(
			НСтр(
			"ru = 'Неправильный формат параметра ИмяПроцедуры (передано значение: ""%1"") в ОбщегоНазначения.ВыполнитьМетодКонфигурации'"),
			ИмяПроцедуры);
	КонецЕсли;

	ИмяОбъекта = ЧастиИмени[0];
	Если ЧастиИмени.Количество() = 2 И Метаданные.ОбщиеМодули.Найти(ИмяОбъекта) = Неопределено Тогда
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'Неправильный формат параметра ИмяПроцедуры (передано значение: ""%1"") в ОбщегоНазначения.ВыполнитьМетодКонфигурации:
				 |Не найден общий модуль ""%2"".'"), ИмяПроцедуры, ИмяОбъекта);
	КонецЕсли;

	Если ЧастиИмени.Количество() = 3 Тогда
		ПолноеИмяОбъекта = ЧастиИмени[0] + "." + ЧастиИмени[1];
		Попытка
			Менеджер = МенеджерОбъектаПоИмени(ПолноеИмяОбъекта);
		Исключение
			Менеджер = Неопределено;
		КонецПопытки;
		Если Менеджер = Неопределено Тогда
			ВызватьИсключение СтрШаблон(
				НСтр("ru = 'Неправильный формат параметра ИмяПроцедуры (передано значение: ""%1"") в ОбщегоНазначения.ВыполнитьМетодКонфигурации:
					 |Не найден менеджер объекта ""%2"".'"), ИмяПроцедуры, ПолноеИмяОбъекта);
		КонецЕсли;
	КонецЕсли;

	ИмяМетодаОбъекта = ЧастиИмени[ЧастиИмени.ВГраница()];
	ВременнаяСтруктура = Новый Структура;
	Попытка
		// Проверка того, что ИмяПроцедуры является допустимым идентификатором.
		// Например: МояПроцедура.
		ВременнаяСтруктура.Вставить(ИмяМетодаОбъекта);
	Исключение
		ЗаписьЖурналаРегистрации(НСтр("ru = 'Безопасное выполнение метода'",
			УИ_ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, , ,
			ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'Неправильный формат параметра ИмяПроцедуры (передано значение: ""%1"") в ОбщегоНазначения.ВыполнитьМетодКонфигурации:
				 |Имя метода ""%2"" не соответствует требованиям образования имен процедур и функций.'"), ИмяПроцедуры,
			ИмяМетодаОбъекта);
	КонецПопытки;

КонецПроцедуры

// Возвращает менеджер объекта по имени.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
//
// Параметры:
//  Имя - Строка - имя например, "Справочник", "Справочники", "Справочник.Организации".
//
// Возвращаемое значение:
//  СправочникиМенеджер, СправочникМенеджер, ДокументыМенеджер, ДокументМенеджер, ...
// 
Функция МенеджерОбъектаПоИмени(Имя)
	Перем КлассОМ, ИмяОМ, Менеджер;

	ЧастиИмени = СтрРазделить(Имя, ".");

	Если ЧастиИмени.Количество() > 0 Тогда
		КлассОМ = ВРег(ЧастиИмени[0]);
	КонецЕсли;

	Если ЧастиИмени.Количество() > 1 Тогда
		ИмяОМ = ЧастиИмени[1];
	КонецЕсли;

	Если КлассОМ = "ПЛАНОБМЕНА" Или КлассОМ = "ПЛАНЫОБМЕНА" Тогда
		Менеджер = ПланыОбмена;

	ИначеЕсли КлассОМ = "СПРАВОЧНИК" Или КлассОМ = "СПРАВОЧНИКИ" Тогда
		Менеджер = Справочники;

	ИначеЕсли КлассОМ = "ДОКУМЕНТ" Или КлассОМ = "ДОКУМЕНТЫ" Тогда
		Менеджер = Документы;

	ИначеЕсли КлассОМ = "ЖУРНАЛДОКУМЕНТОВ" Или КлассОМ = "ЖУРНАЛЫДОКУМЕНТОВ" Тогда
		Менеджер = ЖурналыДокументов;

	ИначеЕсли КлассОМ = "ПЕРЕЧИСЛЕНИЕ" Или КлассОМ = "ПЕРЕЧИСЛЕНИЯ" Тогда
		Менеджер = Перечисления;

	ИначеЕсли КлассОМ = "ОБЩИЙМОДУЛЬ" Или КлассОМ = "ОБЩИЕМОДУЛИ" Тогда

		Возврат ОбщийМодуль(ИмяОМ);

	ИначеЕсли КлассОМ = "ОТЧЕТ" Или КлассОМ = "ОТЧЕТЫ" Тогда
		Менеджер = Отчеты;

	ИначеЕсли КлассОМ = "ОБРАБОТКА" Или КлассОМ = "ОБРАБОТКИ" Тогда
		Менеджер = Обработки;

	ИначеЕсли КлассОМ = "ПЛАНВИДОВХАРАКТЕРИСТИК" Или КлассОМ = "ПЛАНЫВИДОВХАРАКТЕРИСТИК" Тогда
		Менеджер = ПланыВидовХарактеристик;

	ИначеЕсли КлассОМ = "ПЛАНСЧЕТОВ" Или КлассОМ = "ПЛАНЫСЧЕТОВ" Тогда
		Менеджер = ПланыСчетов;

	ИначеЕсли КлассОМ = "ПЛАНВИДОВРАСЧЕТА" Или КлассОМ = "ПЛАНЫВИДОВРАСЧЕТА" Тогда
		Менеджер = ПланыВидовРасчета;

	ИначеЕсли КлассОМ = "РЕГИСТРСВЕДЕНИЙ" Или КлассОМ = "РЕГИСТРЫСВЕДЕНИЙ" Тогда
		Менеджер = РегистрыСведений;

	ИначеЕсли КлассОМ = "РЕГИСТРНАКОПЛЕНИЯ" Или КлассОМ = "РЕГИСТРЫНАКОПЛЕНИЯ" Тогда
		Менеджер = РегистрыНакопления;

	ИначеЕсли КлассОМ = "РЕГИСТРБУХГАЛТЕРИИ" Или КлассОМ = "РЕГИСТРЫБУХГАЛТЕРИИ" Тогда
		Менеджер = РегистрыБухгалтерии;

	ИначеЕсли КлассОМ = "РЕГИСТРРАСЧЕТА" Или КлассОМ = "РЕГИСТРЫРАСЧЕТА" Тогда

		Если ЧастиИмени.Количество() < 3 Тогда
			// Регистр расчета
			Менеджер = РегистрыРасчета;
		Иначе
			КлассПодчиненногоОМ = ВРег(ЧастиИмени[2]);
			Если ЧастиИмени.Количество() > 3 Тогда
				ИмяПодчиненногоОМ = ЧастиИмени[3];
			КонецЕсли;
			Если КлассПодчиненногоОМ = "ПЕРЕРАСЧЕТ" Или КлассПодчиненногоОМ = "ПЕРЕРАСЧЕТЫ" Тогда
				// Перерасчет
				Попытка
					Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты;
					ИмяОМ = ИмяПодчиненногоОМ;
				Исключение
					Менеджер = Неопределено;
				КонецПопытки;
			КонецЕсли;
		КонецЕсли;

	ИначеЕсли КлассОМ = "БИЗНЕСПРОЦЕСС" Или КлассОМ = "БИЗНЕСПРОЦЕССЫ" Тогда
		Менеджер = БизнесПроцессы;

	ИначеЕсли КлассОМ = "ЗАДАЧА" Или КлассОМ = "ЗАДАЧИ" Тогда
		Менеджер = Задачи;

	ИначеЕсли КлассОМ = "КОНСТАНТА" Или КлассОМ = "КОНСТАНТЫ" Тогда
		Менеджер = Константы;

	ИначеЕсли КлассОМ = "ПОСЛЕДОВАТЕЛЬНОСТЬ" Или КлассОМ = "ПОСЛЕДОВАТЕЛЬНОСТИ" Тогда
		Менеджер = Последовательности;
	КонецЕсли;

	Если Менеджер <> Неопределено Тогда
		Если ЗначениеЗаполнено(ИмяОМ) Тогда
			Попытка
				Возврат Менеджер[ИмяОМ];
			Исключение
				Менеджер = Неопределено;
			КонецПопытки;
		Иначе
			Возврат Менеджер;
		КонецЕсли;
	КонецЕсли;

	ВызватьИсключение СтрШаблон(НСтр("ru = 'Не удалось получить менеджер для объекта ""%1""'"), Имя);

КонецФункции

Процедура ХранилищеСохранить(МенеджерХранилища, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек,
	ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения)
	УстановитьПривилегированныйРежим(Истина);

	МенеджерХранилища.Сохранить(КлючОбъекта, КлючНастроек(КлючНастроек), Настройки, ОписаниеНастроек, ИмяПользователя);

	Если ОбновитьПовторноИспользуемыеЗначения Тогда
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;
	УстановитьПривилегированныйРежим(Ложь);

КонецПроцедуры

Функция ХранилищеЗагрузить(МенеджерХранилища, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек,
	ИмяПользователя)

	Результат = Неопределено;
	УстановитьПривилегированныйРежим(Истина);

	Результат = МенеджерХранилища.Загрузить(КлючОбъекта, КлючНастроек(КлючНастроек), ОписаниеНастроек,
			ИмяПользователя);

	Если Результат = Неопределено Тогда
		Результат = ЗначениеПоУмолчанию;
	Иначе
		Если УдалитьБитыеСсылки(Результат) Тогда
			Результат = ЗначениеПоУмолчанию;
		КонецЕсли;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Ложь);
	Возврат Результат;

КонецФункции

Процедура ХранилищеУдалить(МенеджерХранилища, КлючОбъекта, КлючНастроек, ИмяПользователя)

	УстановитьПривилегированныйРежим(Истина);
	МенеджерХранилища.Удалить(КлючОбъекта, КлючНастроек(КлючНастроек), ИмяПользователя);
	УстановитьПривилегированныйРежим(Ложь);

КонецПроцедуры


// Возвращает строку ключа настроек, не превышающую допустимую длину 128 символов.
// Если указанная строка превышает 128, тогда вместо символов сверх 96 символов
// добавляется их хеш-сумма по алгоритму MD5 размером 32 символа.
//
// Параметры:
//  Строка - Строка - строка произвольной длины.
//
// Возвращаемое значение:
//  Строка - не более 128 символов.
//
Функция КлючНастроек(Знач Строка)
	Возврат СократитьСтрокуКонтрольнойСуммой(Строка, 128);
КонецФункции

// Сокращает строку до нужной длины, при этом обрезанная часть хешируется,
// обеспечивая уникальность строки. Проверяет длину строки на входе и, в случае
// превышения максимальной длины, преобразует ее конец по алгоритму MD5 в
// уникальную строку из 32 символов.
//
// Параметры:
//  Строка            - Строка - исходная строка произвольной длины.
//  МаксимальнаяДлина - Число  - требуемое максимальное количество символов в строке,
//                               минимальное значение: 32.
// 
// Возвращаемое значение:
//   Строка - строка, не превышающая максимальную длину.
//
Функция СократитьСтрокуКонтрольнойСуммой(Строка, МаксимальнаяДлина) Экспорт
	УИ_ОбщегоНазначенияКлиентСервер.Проверить(МаксимальнаяДлина >= 32, НСтр(
		"ru = 'Параметр МаксимальнаяДлина не может быть меньше 32'"),
		"ОбщегоНазначения.СократитьСтрокуКонтрольнойСуммой");

	Результат = Строка;
	Если СтрДлина(Строка) > МаксимальнаяДлина Тогда
		Результат = Лев(Строка, МаксимальнаяДлина - 32);
		ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5);
		ХешированиеДанных.Добавить(Сред(Строка, МаксимальнаяДлина - 32 + 1));
		Результат = Результат + СтрЗаменить(ХешированиеДанных.ХешСумма, " ", "");
	КонецЕсли;
	Возврат Результат;
КонецФункции

// Удаляет битые ссылки из переменной.
//
// Параметры:
//   СсылкаИлиКоллекция - ЛюбаяСсылка, Произвольный - Проверяемый объект или очищаемая коллекция.
//
// Возвращаемое значение: 
//   Булево - 
//       * Истина - СсылкаИлиКоллекция ссылочного типа и объект не найден в базе данных.
//       * Ложь - Когда СсылкаИлиКоллекция не ссылочного типа или объект найден в базе данных.
//
Функция УдалитьБитыеСсылки(СсылкаИлиКоллекция)

	Тип = ТипЗнч(СсылкаИлиКоллекция);

	Если Тип = Тип("Неопределено") Или Тип = Тип("Булево") Или Тип = Тип("Строка") Или Тип = Тип("Число") Или Тип = Тип(
		"Дата") Тогда // Оптимизация - часто используемые примитивные типы.

		Возврат Ложь; // Не ссылка.

	ИначеЕсли Тип = Тип("Массив") Тогда

		Количество = СсылкаИлиКоллекция.Количество();
		Для Номер = 1 По Количество Цикл
			ОбратныйИндекс = Количество - Номер;
			Значение = СсылкаИлиКоллекция[ОбратныйИндекс];
			Если УдалитьБитыеСсылки(Значение) Тогда
				СсылкаИлиКоллекция.Удалить(ОбратныйИндекс);
			КонецЕсли;
		КонецЦикла;

		Возврат Ложь; // Не ссылка.

	ИначеЕсли Тип = Тип("Структура") Или Тип = Тип("Соответствие") Тогда

		Для Каждого КлючИЗначение Из СсылкаИлиКоллекция Цикл
			Значение = КлючИЗначение.Значение;
			Если УдалитьБитыеСсылки(Значение) Тогда
				СсылкаИлиКоллекция.Вставить(КлючИЗначение.Ключ, Неопределено);
			КонецЕсли;
		КонецЦикла;

		Возврат Ложь; // Не ссылка.

	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Или Справочники.ТипВсеСсылки().СодержитТип(Тип)
		Или Перечисления.ТипВсеСсылки().СодержитТип(Тип) Или ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип)
		Или ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Или ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип)
		Или ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Или БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип)
		Или Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда
		// Ссылочный тип, исключая ТочкаМаршрутаБизнесПроцессаСсылка.

		Если СсылкаИлиКоллекция.Пустая() Тогда
			Возврат Ложь; // Ссылка пустая.
		ИначеЕсли ЗначениеРеквизитаОбъекта(СсылкаИлиКоллекция, "Ссылка") = Неопределено Тогда
			СсылкаИлиКоллекция = Неопределено;
			Возврат Истина; // "Битая" ссылка.
		Иначе
			Возврат Ложь; // Объект найден.
		КонецЕсли;

	Иначе

		Возврат Ложь; // Не ссылка.

	КонецЕсли;

КонецФункции

// Структура, содержащая значения реквизитов, прочитанные из информационной базы по ссылке на объект.
//
// Если необходимо зачитать реквизит независимо от прав текущего пользователя,
// то следует использовать предварительный переход в привилегированный режим.
//
// Параметры:
//  Ссылка    - ЛюбаяСсылка - объект, значения реквизитов которого необходимо получить.
//            - Строка      - полное имя предопределенного элемента, значения реквизитов которого необходимо получить.
//  Реквизиты - Строка - имена реквизитов, перечисленные через запятую, в формате
//                       требований к свойствам структуры.
//                       Например, "Код, Наименование, Родитель".
//            - Структура, ФиксированнаяСтруктура - в качестве ключа передается
//                       псевдоним поля для возвращаемой структуры с результатом, а в качестве
//                       значения (опционально) фактическое имя поля в таблице.
//                       Если ключ задан, а значение не определено, то имя поля берется из ключа.
//            - Массив, ФиксированныйМассив - имена реквизитов в формате требований
//                       к свойствам структуры.
//  ВыбратьРазрешенные - Булево - если Истина, то запрос к объекту выполняется с учетом прав пользователя, и в случае,
//                                    - если есть ограничение на уровне записей, то все реквизиты вернутся 
//                                      со значением Неопределено;
//                                    - если нет прав для работы с таблицей, то возникнет исключение.
//                              - если Ложь, то возникнет исключение при отсутствии прав на таблицу 
//                                или любой из реквизитов.
//
// Возвращаемое значение:
//  Структура - содержит имена (ключи) и значения затребованных реквизитов.
//            - если в параметр Реквизиты передана пустая строка, то возвращается пустая структура.
//            - если в параметр Ссылка передана пустая ссылка, то возвращается структура, 
//              соответствующая именам реквизитов со значениями Неопределено.
//            - если в параметр Ссылка передана ссылка несуществующего объекта (битая ссылка), 
//              то все реквизиты вернутся со значением Неопределено.
//
Функция ЗначенияРеквизитовОбъекта(Ссылка, Знач Реквизиты, ВыбратьРазрешенные = Ложь) Экспорт
	
	// Если передано имя предопределенного. 
	Если ТипЗнч(Ссылка) = Тип("Строка") Тогда

		ПолноеИмяПредопределенногоЭлемента = Ссылка;
		
		// Вычисление ссылки по имени предопределенного.
		// - дополнительно выполняет проверку метаданных предопределенного, выполняется предварительно.
		Попытка
			Ссылка = УИ_ОбщегоНазначенияКлиентСервер.ПредопределенныйЭлемент(ПолноеИмяПредопределенногоЭлемента);
		Исключение
			ТекстОшибки = СтрШаблон(
			НСтр("ru = 'Неверный первый параметр Ссылка:
				 |%1'"), КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			ВызватьИсключение ТекстОшибки;
		КонецПопытки;
		
		// Разбор полного имени предопределенного.
		ЧастиПолногоИмени = СтрРазделить(ПолноеИмяПредопределенногоЭлемента, ".");
		ПолноеИмяОбъектаМетаданных = ЧастиПолногоИмени[0] + "." + ЧастиПолногоИмени[1];
		
		// Если предопределенный не создан в ИБ, то требуется выполнить проверку доступа к объекту.
		// В других сценариях проверка доступа выполняется в момент исполнения запроса.
		Если Ссылка = Неопределено Тогда

			МетаданныеОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъектаМетаданных);

			Если Не ПравоДоступа("Чтение", МетаданныеОбъекта) Тогда
				ВызватьИсключение СтрШаблон(
						НСтр("ru = 'Недостаточно прав для работы с таблицей ""%1""'"), ПолноеИмяОбъектаМетаданных);
			КонецЕсли;

		КонецЕсли;

	Иначе // Если передана ссылка.

		Попытка
			ПолноеИмяОбъектаМетаданных = Ссылка.Метаданные().ПолноеИмя();
		Исключение
			ВызватьИсключение НСтр("ru = 'Неверный первый параметр Ссылка: 
								   |- Значение должно быть ссылкой или именем предопределенного элемента'");
		КонецПопытки;

	КонецЕсли;
	
	// Разбор реквизитов, если второй параметр Строка.
	Если ТипЗнч(Реквизиты) = Тип("Строка") Тогда
		Если ПустаяСтрока(Реквизиты) Тогда
			Возврат Новый Структура;
		КонецЕсли;
		
		// Удаление пробелов.
		Реквизиты = СтрЗаменить(Реквизиты, " ", "");
		// Преобразование параметра в массив полей.
		Реквизиты = СтрРазделить(Реквизиты, ",");
	КонецЕсли;
	
	// Приведение реквизитов к единому формату.
	СтруктураПолей = Новый Структура;
	Если ТипЗнч(Реквизиты) = Тип("Структура") Или ТипЗнч(Реквизиты) = Тип("ФиксированнаяСтруктура") Тогда

		СтруктураПолей = Реквизиты;

	ИначеЕсли ТипЗнч(Реквизиты) = Тип("Массив") Или ТипЗнч(Реквизиты) = Тип("ФиксированныйМассив") Тогда

		Для Каждого Реквизит Из Реквизиты Цикл

			Попытка
				ПсевдонимПоля = СтрЗаменить(Реквизит, ".", "");
				СтруктураПолей.Вставить(ПсевдонимПоля, Реквизит);
			Исключение 
				// Если псевдоним не является ключом.
				
				// Поиск ошибки доступности полей.
				Результат = НайтиОшибкуДоступностиРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, Реквизиты);
				Если Результат.Ошибка Тогда
					ВызватьИсключение СтрШаблон(
						НСтр("ru = 'Неверный второй параметр Реквизиты: %1'"), Результат.ОписаниеОшибки);
				КонецЕсли;
				
				// Не удалось распознать ошибку, проброс первичной ошибки.
				ВызватьИсключение;

			КонецПопытки;
		КонецЦикла;
	Иначе
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'Неверный тип второго параметра Реквизиты: %1'"), Строка(ТипЗнч(Реквизиты)));
	КонецЕсли;
	
	// Подготовка результата (после выполнения запроса переопределится).
	Результат = Новый Структура;
	
	// Формирование текста запроса к выбираемым полям.
	ТекстЗапросаПолей = "";
	Для Каждого КлючИЗначение Из СтруктураПолей Цикл

		ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ);
		ПсевдонимПоля = КлючИЗначение.Ключ;

		ТекстЗапросаПолей = ТекстЗапросаПолей + ?(ПустаяСтрока(ТекстЗапросаПолей), "", ",") + "
																							  |	" + ИмяПоля
			+ " КАК " + ПсевдонимПоля;
		
		
		// Предварительное добавление поля по псевдониму в возвращаемый результат.
		Результат.Вставить(ПсевдонимПоля);

	КонецЦикла;
	
	// Если предопределенного нет в ИБ.
	// - приведение результата к отсутствию объекта в ИБ или передаче пустой ссылки.
	Если Ссылка = Неопределено Тогда
		Возврат Результат;
	КонецЕсли;

	ТекстЗапроса = "ВЫБРАТЬ " + ?(ВыбратьРазрешенные, "РАЗРЕШЕННЫЕ", "") + "
																		   |" + ТекстЗапросаПолей + "
																									|ИЗ
																									|	"
		+ ПолноеИмяОбъектаМетаданных + " КАК Таблица
									   |ГДЕ
									   |	Таблица.Ссылка = &Ссылка
									   |";
	
	// Выполнение запроса.
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	Запрос.Текст = ТекстЗапроса;

	Попытка
		Выборка = Запрос.Выполнить().Выбрать();
	Исключение
		
		// Если реквизиты были переданы строкой, то они уже конвертированы в массив.
		// Если реквизиты - массив, оставляем без изменений.
		// Если реквизиты - структура - конвертируем в массив.
		// В остальных случаях уже было бы выброшено исключение.
		Если Тип("Структура") = ТипЗнч(Реквизиты) Тогда
			Реквизиты = Новый Массив;
			Для Каждого КлючИЗначение Из СтруктураПолей Цикл
				ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ);
				Реквизиты.Добавить(ИмяПоля);
			КонецЦикла;
		КонецЕсли;
		
		// Поиск ошибки доступности полей.
		Результат = НайтиОшибкуДоступностиРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, Реквизиты);
		Если Результат.Ошибка Тогда
			ВызватьИсключение СтрШаблон(
				НСтр("ru = 'Неверный второй параметр Реквизиты: %1'"), Результат.ОписаниеОшибки);
		КонецЕсли;
		
		// Не удалось распознать ошибку, проброс первичной ошибки.
		ВызватьИсключение;

	КонецПопытки;
	
	// Заполнение реквизитов.
	Если Выборка.Следующий() Тогда
		ЗаполнитьЗначенияСвойств(Результат, Выборка);
	КонецЕсли;

	Возврат Результат;

КонецФункции

// Значение реквизита, прочитанного из информационной базы по ссылке на объект.
//
// Если необходимо зачитать реквизит независимо от прав текущего пользователя,
// то следует использовать предварительный переход в привилегированный режим.
//
// Параметры:
//  Ссылка    - ЛюбаяСсылка - объект, значения реквизитов которого необходимо получить.
//            - Строка      - полное имя предопределенного элемента, значения реквизитов которого необходимо получить.
//  ИмяРеквизита       - Строка - имя получаемого реквизита.
//  ВыбратьРазрешенные - Булево - если Истина, то запрос к объекту выполняется с учетом прав пользователя, и в случае,
//                                    - если есть ограничение на уровне записей, то возвращается Неопределено;
//                                    - если нет прав для работы с таблицей, то возникнет исключение.
//                              - если Ложь, то возникнет исключение при отсутствии прав на таблицу
//                                или любой из реквизитов.
//
// Возвращаемое значение:
//  Произвольный - зависит от типа значения прочитанного реквизита.
//               - если в параметр Ссылка передана пустая ссылка, то возвращается Неопределено.
//               - если в параметр Ссылка передана ссылка несуществующего объекта (битая ссылка), 
//                 то возвращается Неопределено.
//
Функция ЗначениеРеквизитаОбъекта(Ссылка, ИмяРеквизита, ВыбратьРазрешенные = Ложь) Экспорт

	Если ПустаяСтрока(ИмяРеквизита) Тогда
		ВызватьИсключение НСтр("ru = 'Неверный второй параметр ИмяРеквизита: 
							   |- Имя реквизита должно быть заполнено'");
	КонецЕсли;

	Результат = ЗначенияРеквизитовОбъекта(Ссылка, ИмяРеквизита, ВыбратьРазрешенные);
	Возврат Результат[СтрЗаменить(ИмяРеквизита, ".", "")];

КонецФункции 

// Выполняет поиск проверяемых выражений среди реквизитов объекта метаданных.
// 
// Параметры:
//  ПолноеИмяОбъектаМетаданных - Строка - полное имя проверяемого объекта.
//  ПроверяемыеВыражения       - Массив - имена полей или проверяемые выражения объекта метаданных.
// 
// Возвращаемое значение:
//  Структура - Результат проверки.
//  * Ошибка         - Булево - Найдена ошибка.
//  * ОписаниеОшибки - Строка - Описание найденных ошибок.
//
// Пример:
//  
// Реквизиты = Новый Массив;
// Реквизиты.Добавить("Номер");
// Реквизиты.Добавить("Валюта.НаименованиеПолное");
//
// Результат = ОбщегоНазначения.НайтиОшибкуДоступностиРеквизитовОбъекта("Документ._ДемоЗаказПокупателя", Реквизиты);
//
// Если Результат.Ошибка Тогда
//     ВызватьИсключение Результат.ОписаниеОшибки;
// КонецЕсли;
//
Функция НайтиОшибкуДоступностиРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, ПроверяемыеВыражения)

	МетаданныеОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъектаМетаданных);

	Если МетаданныеОбъекта = Неопределено Тогда
		Возврат Новый Структура("Ошибка, ОписаниеОшибки", Истина, СтрШаблон(НСтр(
			"ru = 'Ошибка получения метаданных ""%1""'"), ПолноеИмяОбъектаМетаданных));
	КонецЕсли;

	// Разрешение вызова из безопасного режима внешней обработки или расширения.
	// Информация о доступности полей источника схемы при проверке метаданных не является секретной.
	УстановитьОтключениеБезопасногоРежима(Истина);
	УстановитьПривилегированныйРежим(Истина);

	Схема = Новый СхемаЗапроса;
	Пакет = Схема.ПакетЗапросов.Добавить(Тип("ЗапросВыбораСхемыЗапроса"));
	Оператор = Пакет.Операторы.Получить(0);

	Источник = Оператор.Источники.Добавить(ПолноеИмяОбъектаМетаданных, "Таблица");
	ТекстОшибки = "";

	Для Каждого ТекущееВыражение Из ПроверяемыеВыражения Цикл

		Если Не ПолеИсточникаСхемыЗапросаДоступно(Источник, ТекущееВыражение) Тогда
			ТекстОшибки = ТекстОшибки + Символы.ПС + СтрШаблон(
				НСтр("ru = '- Поле объекта ""%1"" не найдено'"), ТекущееВыражение);
		КонецЕсли;

	КонецЦикла;

	Возврат Новый Структура("Ошибка, ОписаниеОшибки", Не ПустаяСтрока(ТекстОшибки), ТекстОшибки);

КонецФункции

// Используется в НайтиОшибкуДоступностиРеквизитовОбъекта.
// Выполняет проверку доступности поля проверяемого выражения в источнике оператора схемы запроса.
//
Функция ПолеИсточникаСхемыЗапросаДоступно(ИсточникОператора, ПроверяемоеВыражение)

	ЧастиИмениПоля = СтрРазделить(ПроверяемоеВыражение, ".");
	ДоступныеПоля = ИсточникОператора.Источник.ДоступныеПоля;

	ТекущаяЧастьИмениПоля = 0;
	Пока ТекущаяЧастьИмениПоля < ЧастиИмениПоля.Количество() Цикл

		ТекущееПоле = ДоступныеПоля.Найти(ЧастиИмениПоля.Получить(ТекущаяЧастьИмениПоля));

		Если ТекущееПоле = Неопределено Тогда
			Возврат Ложь;
		КонецЕсли;
		
		// Инкрементация следующей части имени поля и соответствующего списка доступности полей.
		ТекущаяЧастьИмениПоля = ТекущаяЧастьИмениПоля + 1;
		ДоступныеПоля = ТекущееПоле.Поля;

	КонецЦикла;

	Возврат Истина;

КонецФункции

// Возвращает Истина, если эта информационная база подключена к 1С:Fresh.
//
// Возвращаемое значение:
//  Булево - признак автономного рабочего места.
//
Функция ЭтоАвтономноеРабочееМесто() Экспорт

//	Если ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
//		МодульОбменДаннымиСервер = ОбщийМодуль("ОбменДаннымиСервер");
//		Возврат МодульОбменДаннымиСервер.ЭтоАвтономноеРабочееМесто();
//	КонецЕсли;

	Возврат Ложь;

КонецФункции

Функция ЕстьПравоНаИспользованиеИнструментов() Экспорт
	Возврат ПравоДоступа("Просмотр", Метаданные.Подсистемы.УИ_УниверсальныеИнструменты);
КонецФункции

// Это веб клиент.
// 
// Возвращаемое значение:
//  Булево - Это веб клиент
Функция ЭтоВебКлиент() Экспорт
	ПараметрыСеансаВХранилище = УИ_ОбщегоНазначенияВызовСервера.ХранилищеОбщихНастроекЗагрузить(
		УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек(),
		УИ_ОбщегоНазначенияКлиентСервер.КлючНастроекПараметровСеанса());
	
	ЭтоВебКлиент = Ложь;
	Если ТипЗнч(ПараметрыСеансаВХранилище) = Тип("Структура") Тогда
		Если ПараметрыСеансаВХранилище.Свойство("ЭтоВебКлиент") Тогда
			ЭтоВебКлиент = ПараметрыСеансаВХранилище.ЭтоВебКлиент;
		КонецЕсли;
	КонецЕсли;

	Возврат ЭтоВебКлиент;	
КонецФункции


// Версия БСП.
// 
// Возвращаемое значение:
//  Строка - Версия БСП
Функция ВерсияБСП() Экспорт
	Перем ВерсияБСП;
	УстановитьБезопасныйРежим(Истина);
	
	Попытка
		Выполнить("ВерсияБСП = СтандартныеПодсистемыСервер.ВерсияБиблиотеки()");
	Исключение
		Попытка
			Выполнить("ВерсияБСП = СтандартныеПодсистемыПереопределяемый.ВерсияБиблиотеки()");
		Исключение
			ВерсияБСП = "0.0.0.0";	// Неопределено. см. БСП_ДоступнаТребуемаяВерсия()
		КонецПопытки;
	КонецПопытки;
	
	Возврат ВерсияБСП;
	
КонецФункции

// Результат установки прав доступа для БСП 3 1 6 и выше.
// 
// Возвращаемое значение:
//  Булево - Результат установки прав доступа для БСП 3 1 6 и выше
Функция РезультатУстановкиПравДоступаДляБСП_3_1_6_ИВыше() Экспорт
	Код = "
		  |ПрофильДоступаАдминистратор	= УправлениеДоступом.ПрофильАдминистратор();
		  |ПрофильОбъект = ПрофильДоступаАдминистратор.ПолучитьОбъект();
		  |ПрофильОбъект.Записать();
		  |УправлениеДоступом.ОбновитьРолиПользователей();
		  |";

	УстановитьБезопасныйРежим(Истина);
	Попытка
		Выполнить (Код);
		Возврат Истина;
	Исключение
		УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось применить права доступа для УИ. 
															 |Они будут применены автоматически позже о чем будет выведено сообщение
															 |"+ОписаниеОшибки());
		Возврат Ложь;
	КонецПопытки;

КонецФункции

// Обеспечить каталог.
// 
// Параметры:
//  Каталог -Строка -Каталог
Процедура ОбеспечитьКаталог(Каталог) Экспорт
	Файл = Новый Файл(Каталог);
	Если Файл.Существует() Тогда
		Возврат;
	КонецЕсли;
	СоздатьКаталог(Каталог);
КонецПроцедуры

// Каталог вспомогательных библиотек инструментов на сервере.
// 
// Возвращаемое значение:
//  Строка - Каталог вспомогательных библиотек инструментов на сервере
Функция КаталогДанныхИнструментовНаСервере() Экспорт
	КаталогДанныхИнструментовНаСервере = КаталогДанныхИнструментовНаСервереИзНастроек();
	Если ЗначениеЗаполнено(КаталогДанныхИнструментовНаСервере) Тогда
		Возврат КаталогДанныхИнструментовНаСервере;
	Иначе
		Возврат КаталогДанныхИнструментовНаСервереПоУмолчанию();
	КонецЕсли;
КонецФункции

// Каталог файлов данных отладки на сервере.
// 
// Возвращаемое значение:
//  Строка - Каталог файлов данных отладки на сервере
Функция КаталогФайловДанныхОтладкиНаСервере() Экспорт
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОбъединитьПути(КаталогДанныхИнструментовНаСервере(),
														   "ДанныеОтладки");
КонецФункции

// Каталог файлов tool1 CDНа сервере.
// 
// Возвращаемое значение:
//  Строка -  Каталог файлов tool1 CDНа сервере
Функция КаталогФайловTool1CDНаСервере() Экспорт
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОбъединитьПути(КаталогДанныхИнструментовНаСервере(), "ctool1cd");

КонецФункции

#Область РаботаСФормамиИнструментов

Процедура ДобавитьВКоманднуюПанельОбщиеКоманды(Форма, ОсновнаяКоманднаяПанельФормы)
	Если Форма.ПоложениеКоманднойПанели=ПоложениеКоманднойПанелиФормы.Нет 
		И ОсновнаяКоманднаяПанельФормы=Неопределено Тогда
		Возврат;
	КонецЕсли;

	Если ОсновнаяКоманднаяПанельФормы=Неопределено Тогда
		КоманднаяПанель= Форма.КоманднаяПанель;
	Иначе
		КоманднаяПанель=ОсновнаяКоманднаяПанельФормы;
	КонецЕсли;
	
	ОписаниеКоманды = УИ_РаботаСФормами.НовыйОписаниеКомандыКнопки();
	ОписаниеКоманды.Имя = "УИ_ОткрытьНовуюФормуИнструмента";
	ОписаниеКоманды.ИмяКоманды = ОписаниеКоманды.Имя;
	ОписаниеКоманды.Действие="Подключаемый_ВыполнитьОбщуюКомандуИнструментов";
	ОписаниеКоманды.РодительЭлемента=КоманднаяПанель;
	ОписаниеКоманды.Картинка = БиблиотекаКартинок.НовоеОкно;
	ОписаниеКоманды.Отображение = ОтображениеКнопки.Картинка;
	ОписаниеКоманды.Подсказка = "Открывает еще одну пустую форму текущего инструмента";
	ОписаниеКоманды.Заголовок = "Открыть новую форму";
	УИ_РаботаСФормами.СоздатьКомандуПоОписанию(Форма, ОписаниеКоманды);
	УИ_РаботаСФормами.СоздатьКнопкуПоОписанию(Форма, ОписаниеКоманды);
КонецПроцедуры

Процедура ФормаИнструментаПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка, ОсновнаяКоманднаяПанельФормы = Неопределено) Экспорт
	ДобавитьВКоманднуюПанельОбщиеКоманды(Форма, ОсновнаяКоманднаяПанельФормы);
КонецПроцедуры

#КонецОбласти

#Область ИнструментПросмотрЗначений

// Установить условное оформление таблицы значений.
// 
// Параметры:
//  Форма -  ФормаКлиентскогоПриложения
//  ЭлементТаблицыДереваФормы  - ТаблицаФормы -Элемент таблицы дерева формы
//  ИмяРеквизитаТаблицыФормы - Строка -Имя реквизита таблицы формы
//  ОчищатьОформление - Булево - Очищать оформление
Процедура УстановитьУсловноеОформлениеТаблицыЗначенийПросмотраЗначений(Форма, ЭлементТаблицыДереваФормы, ИмяРеквизитаТаблицыФормы,
	ОчищатьОформление = Истина) Экспорт
	Если ОчищатьОформление Тогда
		Форма.УсловноеОформление.Элементы.Очистить();
	КонецЕсли;

	НовыйЭлементОформления = Форма.УсловноеОформление.Элементы.Добавить();
	НовыйЭлементОформления.Использование = Истина;

	Поле = НовыйЭлементОформления.Поля.Элементы.Добавить();
	Поле.Использование = Истина;
	Поле.Поле = Новый ПолеКомпоновкиДанных(ЭлементТаблицыДереваФормы.имя);

	УИ_ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора(НовыйЭлементОформления.Отбор,
															ИмяРеквизитаТаблицыФормы + ".ЗначениеЕстьОшибка",
															Истина);

	НовыйЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.ЛососьСветлый);

КонецПроцедуры

#КонецОбласти

#Область НастройкиИнструментов

Функция КаталогДанныхИнструментовНаСервереПоУмолчанию() Экспорт
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОбъединитьПути(КаталогВременныхФайлов(), "tools_ui_1c");

КонецФункции

// Каталог данных инструментов на сервере из настроек.
// 
// Возвращаемое значение:
//  Строка -  Каталог данных инструментов на сервере из настроек
Функция КаталогДанныхИнструментовНаСервереИзНастроек() Экспорт
	Возврат ХранилищеОбщихНастроекЗагрузить(УИ_ОбщегоНазначенияКлиентСервер.КлючДанныхНастроекВХранилищеНастроек(),
											УИ_ОбщегоНазначенияКлиентСервер.ИмяСохраненнойНастройкиКаталогаИнструментовНаСервере(),
											"");

КонецФункции


// Сохранить каталог данных инструментов на сервере в настройки.
// 
// Параметры:
//  Каталог - Строка- Каталог
Процедура СохранитьКаталогДанныхИнструментовНаСервереВНастройки(Каталог) Экспорт
	ХранилищеОбщихНастроекСохранить(УИ_ОбщегоНазначенияКлиентСервер.КлючДанныхНастроекВХранилищеНастроек(),
									УИ_ОбщегоНазначенияКлиентСервер.ИмяСохраненнойНастройкиКаталогаИнструментовНаСервере(),
									Каталог);
КонецПроцедуры

#КонецОбласти

// Подключить внешнюю обработку к сеансу.
// 
// Параметры:
//  АдресДвоичныхДанныхОбработки -Строка-Адрес двоичных данных обработки
//  ИмяОбработки - Неопределено, Строка - Имя обработки
Процедура ПодключитьВнешнююОбработкуКСеансу(АдресДвоичныхДанныхОбработки, ИмяОбработки = Неопределено) Экспорт
	ОписаниеЗащитыОтОпасныхДействий = Новый ОписаниеЗащитыОтОпасныхДействий;
	ОписаниеЗащитыОтОпасныхДействий.ПредупреждатьОбОпасныхДействиях=Ложь;
	Если ИмяОбработки = Неопределено Тогда
		ВнешниеОбработки.Подключить(АдресДвоичныхДанныхОбработки, , Ложь, ОписаниеЗащитыОтОпасныхДействий);
	Иначе

		ВнешниеОбработки.Подключить(АдресДвоичныхДанныхОбработки, ИмяОбработки, Ложь, ОписаниеЗащитыОтОпасныхДействий);
	КонецЕсли;
КонецПроцедуры

// Возвращает исключения при поиске мест использования объектов.
//
// Возвращаемое значение:
//   Соответствие - Исключения поиска ссылок в разрезе объектов метаданных:
//       * Ключ - ОбъектМетаданных - Объект метаданных, для которого применяются исключения.
//       * Значение - Строка, Массив - описание исключенных реквизитов.
//           Если "*", то исключены все реквизиты объекта метаданных.
//           Если массив строк, то содержит относительные имена исключенных реквизитов.
//
Функция ИсключенияПоискаСсылок() Экспорт

	ИсключенияПоискаИнтеграция = Новый Массив;

//	МодульИнтеграцияПодсистемБСП=ОбщийМодуль("ИнтеграцияПодсистемБСП");
//	Если МодульИнтеграцияПодсистемБСП <> Неопределено Тогда
//		МодульИнтеграцияПодсистемБСП.ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоискаИнтеграция);
//	КонецЕсли;

	ИсключенияПоиска = Новый Массив;
//	МодульОбщегоНазначенияПереопределяемый=ОбщийМодуль("ОбщегоНазначенияПереопределяемый");
//	Если МодульОбщегоНазначенияПереопределяемый <> Неопределено Тогда
//		МодульОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоиска);
//	КонецЕсли;

	УИ_ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИсключенияПоиска, ИсключенияПоискаИнтеграция);

	Результат = Новый Соответствие;
	Для Каждого ИсключениеПоиска Из ИсключенияПоиска Цикл
		// Определение полного имени реквизита и объекта метаданных - носителя реквизита.
		Если ТипЗнч(ИсключениеПоиска) = Тип("Строка") Тогда
			ПолноеИмя          = ИсключениеПоиска;
			МассивПодстрок     = СтрРазделить(ПолноеИмя, ".");
			КоличествоПодстрок = МассивПодстрок.Количество();
			ОбъектМетаданных   = Метаданные.НайтиПоПолномуИмени(МассивПодстрок[0] + "." + МассивПодстрок[1]);
		Иначе
			ОбъектМетаданных   = ИсключениеПоиска;
			ПолноеИмя          = ОбъектМетаданных.ПолноеИмя();
			МассивПодстрок     = СтрРазделить(ПолноеИмя, ".");
			КоличествоПодстрок = МассивПодстрок.Количество();
			Если КоличествоПодстрок > 2 Тогда
				Пока Истина Цикл
					Родитель = ОбъектМетаданных.Родитель();
					Если ТипЗнч(Родитель) = Тип("ОбъектМетаданныхКонфигурация") Тогда
						Прервать;
					Иначе
						ОбъектМетаданных = Родитель;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
		// Регистрация.
		Если КоличествоПодстрок < 4 Тогда
			Результат.Вставить(ОбъектМетаданных, "*");
		Иначе
			ПутиКРеквизитам = Результат.Получить(ОбъектМетаданных);
			Если ПутиКРеквизитам = "*" Тогда
				Продолжить; // Весь объект метаданных уже исключен.
			ИначеЕсли ПутиКРеквизитам = Неопределено Тогда
				ПутиКРеквизитам = Новый Массив;
				Результат.Вставить(ОбъектМетаданных, ПутиКРеквизитам);
			КонецЕсли;
			// Формат реквизита:
			//   "<ВидОМ>.<ИмяОМ>.<ТипРеквизитаИлиТЧ>.<ИмяРеквизитаИлиТЧ>[.<ТипРеквизита>.<ИмяРеквизитаТЧ>]".
			//   Примеры:
			//     "РегистрСведений.ВерсииОбъектов.Реквизит.АвторВерсии",
			//     "Документ._ДемоЗаказПокупателя.ТабличнаяЧасть.СчетаНаОплату.Реквизит.Счет",
			//     "ПланВидовРасчета._ДемоОсновныеНачисления.СтандартнаяТабличнаяЧасть.БазовыеВидыРасчета.СтандартныйРеквизит.ВидРасчета".
			// Относительный путь к реквизиту должен получиться таким, чтобы его можно было использовать в условиях запроса:
			//   "<ИмяРеквизитаИлиТЧ>[.<ИмяРеквизитаТЧ>]".
			Если КоличествоПодстрок = 4 Тогда
				ОтносительныйПутьКРеквизиту = МассивПодстрок[3];
			Иначе
				ОтносительныйПутьКРеквизиту = МассивПодстрок[3] + "." + МассивПодстрок[5];
			КонецЕсли;
			ПутиКРеквизитам.Добавить(ОтносительныйПутьКРеквизиту);
		КонецЕсли;
	КонецЦикла;
	Возврат Результат;

КонецФункции

// Подключает компоненту, выполненную по технологии Native API и COM.
// Компонента должна храниться в макете конфигурации в виде ZIP-архива.
//
// Параметры:
//  Идентификатор   - Строка - идентификатор объекта внешней компоненты.
//  ПолноеИмяМакета - Строка - полное имя макета конфигурации, хранящего ZIP-архив.
//
// Возвращаемое значение:
//  AddIn, Неопределено - экземпляр объекта внешней компоненты или Неопределено, если не удалось создать.
//
// Пример:
//
//  ПодключаемыйМодуль = ОбщегоНазначения.ПодключитьКомпонентуИзМакета(
//      "QRCodeExtension",
//      "ОбщийМакет.КомпонентаПечатиQRКода");
//
//  Если ПодключаемыйМодуль <> Неопределено Тогда 
//      // ПодключаемыйМодуль содержит созданный экземпляр подключенной компоненты.
//  КонецЕсли;
//
//  ПодключаемыйМодуль = Неопределено;
//
Функция ПодключитьКомпонентуИзМакета(Идентификатор, ПолноеИмяМакета) Экспорт

	ПодключаемыйМодуль = Неопределено;

	Если Не МакетСуществует(ПолноеИмяМакета) Тогда
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'Не удалось подключить внешнюю компоненту ""%1"" на сервере
				 |из %2
				 |по причине:
				 |Подключение на сервере не из макета запрещено'"), Идентификатор, ПолноеИмяМакета);
	КонецЕсли;

	Местоположение = ПолноеИмяМакета;
	СимволическоеИмя = Идентификатор + "SymbolicName";

	Если ПодключитьВнешнююКомпоненту(Местоположение, СимволическоеИмя) Тогда

		Попытка
			ПодключаемыйМодуль = Новый ("AddIn." + СимволическоеИмя + "." + Идентификатор);
			Если ПодключаемыйМодуль = Неопределено Тогда
				ВызватьИсключение НСтр("ru = 'Оператор Новый вернул Неопределено'");
			КонецЕсли;
		Исключение
			ПодключаемыйМодуль = Неопределено;
			ТекстОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		КонецПопытки;

		Если ПодключаемыйМодуль = Неопределено Тогда

			ТекстОшибки = СтрШаблон(
				НСтр("ru = 'Не удалось создать объект внешней компоненты ""%1"", подключенной на сервере
					 |из макета ""%2"",
					 |по причине:
					 |%3'"), Идентификатор, Местоположение, ТекстОшибки);

			ЗаписьЖурналаРегистрации(
				НСтр("ru = 'Подключение внешней компоненты на сервере'",
				УИ_ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);

		КонецЕсли;

	Иначе

		ТекстОшибки = СтрШаблон(
			НСтр("ru = 'Не удалось подключить внешнюю компоненту ""%1"" на сервере
				 |из макета ""%2""
				 |по причине:
				 |Метод ПодключитьВнешнююКомпоненту вернул Ложь.'"), Идентификатор, Местоположение);

		ЗаписьЖурналаРегистрации(
			НСтр("ru = 'Подключение внешней компоненты на сервере'",
			УИ_ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);

	КонецЕсли;

	Возврат ПодключаемыйМодуль;

КонецФункции


// Возвращает описание предмета в виде текстовой строки.
// 
// Параметры:
//  СсылкаНаПредмет - ЛюбаяСсылка - объект ссылочного типа.
//
// Возвращаемое значение:
//   Строка - представление предмета.
// 
Функция ПредметСтрокой(СсылкаНаПредмет) Экспорт

	Результат = "";
	
	//@skip-warning
	Если СсылкаНаПредмет = Неопределено Или СсылкаНаПредмет.Пустая() Тогда
		Результат = НСтр("ru = 'не задан'");
	ИначеЕсли Метаданные.Документы.Содержит(СсылкаНаПредмет.Метаданные()) Или Метаданные.Перечисления.Содержит(
		СсылкаНаПредмет.Метаданные()) Тогда
		Результат = Строка(СсылкаНаПредмет);
	Иначе	
		//@skip-warning
		ПредставлениеОбъекта = СсылкаНаПредмет.Метаданные().ПредставлениеОбъекта;
		Если ПустаяСтрока(ПредставлениеОбъекта) Тогда
			//@skip-warning
			ПредставлениеОбъекта = СсылкаНаПредмет.Метаданные().Представление();
		КонецЕсли;
		Результат = СтрШаблон("%1 (%2)", Строка(СсылкаНаПредмет), ПредставлениеОбъекта);
	КонецЕсли;

	Возврат Результат;

КонецФункции

Процедура ЗарегистрироватьОшибкуЗамены(Результат, Знач Ссылка, Знач ОписаниеОшибки)

	Результат.ЕстьОшибки = Истина;

	Строка = Результат.Ошибки.Добавить();
	Строка.Ссылка = Ссылка;
	Строка.ПредставлениеОбъектаОшибки = ОписаниеОшибки.ПредставлениеОбъектаОшибки;
	Строка.ОбъектОшибки               = ОписаниеОшибки.ОбъектОшибки;
	Строка.ТекстОшибки                = ОписаниеОшибки.ТекстОшибки;
	Строка.ТипОшибки                  = ОписаниеОшибки.ТипОшибки;

КонецПроцедуры

Функция ОписаниеОшибкиЗамены(Знач ТипОшибки, Знач ОбъектОшибки, Знач ПредставлениеОбъектаОшибки, Знач ТекстОшибки)
	Результат = Новый Структура;

	Результат.Вставить("ТипОшибки", ТипОшибки);
	Результат.Вставить("ОбъектОшибки", ОбъектОшибки);
	Результат.Вставить("ПредставлениеОбъектаОшибки", ПредставлениеОбъектаОшибки);
	Результат.Вставить("ТекстОшибки", ТекстОшибки);

	Возврат Результат;
КонецФункции


#Область Типы




// Описание типа по идентификатору типа.
// 
// Параметры:
//  ИдентификаторТипа - Строка, Массив Из Строка- Идентификатор типа
// 
// Возвращаемое значение:
//  ОписаниеТипов
Функция ОписаниеТипаПоИдентификаторуТипа(ИдентификаторТипа) Экспорт
	СтрокаДляСериализации = УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаСериализованнаяСтрокаЗаголовок();
	Если ТипЗнч(ИдентификаторТипа) = Тип("Массив") Тогда
		Для Каждого ТекТип Из ИдентификаторТипа Цикл
			УИ_ОбщегоНазначенияКлиентСервер.ДобавитьКСериализованнойСтрокеОписанияТипаСтрокуТипа(СтрокаДляСериализации,
																								 ТекТип);
		КонецЦикла;
	Иначе
		УИ_ОбщегоНазначенияКлиентСервер.ДобавитьКСериализованнойСтрокеОписанияТипаСтрокуТипа(СтрокаДляСериализации,
																							 ИдентификаторТипа);
	КонецЕсли;

	Возврат ЗначениеИзСтрокиXML(СтрокаДляСериализации
								+ УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаСериализованнаяСтрокаПодвал());

КонецФункции

// Возвращает описание типа, включающего в себя все возможные ссылочные типы конфигурации.
//
// Возвращаемое значение:
//  ОписаниеТипов - все ссылочные типы конфигурации.
//
Функция ОписаниеТипаВсеСсылки() Экспорт

	Возврат УИ_ОбщегоНазначенияПовтИсп.ОписаниеТипаВсеСсылки();

КонецФункции

// Описание типа любая ссылка.
// 
// Возвращаемое значение:
//  Строка - Описание типа любая ссылка
Функция ОписаниеТипаЛюбаяСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаЛюбаяСсылка());
КонецФункции

// Описание типа характиристика плана видов характеристик.
// 
// Параметры:
//  ИмяПланаВидовХарактеристик -Строка-Имя плана видов характеристик
// 
// Возвращаемое значение:
//  ОписаниеТипов, Произвольный - Описание типа характиристика плана видов характеристик
Функция ОписаниеТипаХарактиристикаПланаВидовХарактеристик(ИмяПланаВидовХарактеристик) Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаХарактиристикаПланаВидовХарактеристик(ИмяПланаВидовХарактеристик));
КонецФункции

// Описание типа определяемого типа.
// 
// Параметры:
//  ИмяОпределяемогоТипа - Строка - Имя определяемого типа
// 
// Возвращаемое значение:
//  ОписаниеТипов- Описание типа определяемого типа
Функция ОписаниеТипаОпределяемогоТипа(ИмяОпределяемогоТипа) Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаОпределяемогоТипа(ИмяОпределяемогоТипа));
КонецФункции

// Описание типа CправочникCсылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа справочник ссылка
Функция ОписаниеТипаСправочникСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаСправочникСсылка());
КонецФункции

// Описание типа ДокументCсылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа справочник ссылка
Функция ОписаниеТипаДокументCсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаДокументСсылка());
КонецФункции

// Описание типа бизнесс процесс cсылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа бизнесс процесс cсылка
Функция ОписаниеТипаБизнессПроцессCсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаБизнессПроцессСсылка());
КонецФункции

// Описание типа точка маршрута бизнес процесса ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа точка маршрута бизнес процесса ссылка
Функция ОписаниеТипаТочкаМаршрутаБизнесПроцессаСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаТочкаМаршрутаБизнесПроцессаСсылка());
КонецФункции

// Описание типа план счетов ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа план счетов ссылка
Функция ОписаниеТипаПланСчетовСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаПланСчетовСсылка());
КонецФункции

// Описание тип план видов расчета ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание тип план видов расчета ссылка
Функция ОписаниеТипаПланВидовРасчетаСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаПланВидовРасчетаСсылка());
КонецФункции

// Описание тип план видов характеристик ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание тип план видов характеристик ссылка
Функция ОписаниеТипаПланВидовХарактеристикСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаПланВидовХарактеристикСсылка());
КонецФункции

// Описание тип перечисление ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание тип перечисление ссылка
Функция ОписаниеТипаПеречислениеСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаПеречислениеСсылка());
КонецФункции

// Описание типа план обмена ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа план обмена ссылка
Функция ОписаниеТипаПланОбменаСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаПланОбменаСсылка());
КонецФункции

// Описание типа задача ссылка.
// 
// Возвращаемое значение:
//  ОписаниеТипов - Описание типа задача ссылка
Функция ОписаниеТипаЗадачаСсылка() Экспорт
	Возврат ОписаниеТипаПоИдентификаторуТипа(УИ_ОбщегоНазначенияКлиентСервер.ИдентификаторТипаЗадачаСсылка());
КонецФункции


// Возвращает описание тиров, содержащее примитивные типы.
//
// Возвращаемое значение:
//   ОписаниеТипов
//
Функция ОписаниеПримитивныхТипов() Экспорт
	
	Возврат УИ_ОбщегоНазначенияПовтИсп.ОписаниеПримитивныхТипов();
	
КонецФункции


// Имя типа. Может не всегда давать обратно конвертируемый тип. 
// ЧТо найдется нужно добавлять в исключения. Пока нашелся только один
// 
// Параметры:
//  Тип  - Тип
// 
// Возвращаемое значение:
//  Строка -  Имя типа
Функция ИмяТипа(Тип) Экспорт
	ИмяТипаXML = XMLТип(Тип);
	Если ИмяТипаXML = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	Если ЭтоСсылка(Тип) Тогда
		Возврат СериализаторXDTO.XMLТип(Тип).ИмяТипа;
	Иначе
		//Обрабатываем специфичные вещи, которые в обратный зад могут не сработать
		Если Тип = Тип("ДвоичныеДанные") Тогда
			Возврат "BinaryData";
		КонецЕсли;
	КонецЕсли;
КонецФункции

// Имя объекта метаданных типа.
// 
// Параметры:
//  Тип - Тип
// 
// Возвращаемое значение:
//  Строка - Имя объекта метаданных типа
Функция ИмяОбъектаМетаданныхТипа(Тип) Экспорт
	ОбъектМД = Метаданные.НайтиПоТипу(Тип);
	Если ОбъектМД = Неопределено Тогда
		Возврат "";
	КонецЕсли;
	Возврат ОбъектМД.ПолноеИмя();
КонецФункции

// Заполнить динамические свойства значения.
// 
// Параметры:
// 	ОписаниеТипаПлатформы - см. УИ_ТипыПлатформыКлиентСервер.НовыйОписаниеТипаПлатформы
//  ИмяСвойства - Строка - Имя свойства
//  ИменаСвойств - Массив из Строка - Имена свойств
//  ЗначениеСтрокиДерева - Произвольный - Значение строки дерева
//  ОбъектМД - ОбъектМетаданных - Объект МД
Процедура ЗаполнитьДинамическиеСвойстваЗначения(ОписаниеТипаПлатформы, ИмяСвойства, ИменаСвойств, ЗначениеСтрокиДерева, ОбъектМД) Экспорт

	ИмяДляСравнения = НРег(ИмяСвойства);
	Если ИмяДляСравнения = "<имя ключа>" Тогда
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого КлючЗначение Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(КлючЗначение.Ключ);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя области>"
			  Или ИмяДляСравнения = "<имя рисунка>"
			  Или ИмяДляСравнения = "<имя встроенной таблицы>" Тогда
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого Стр Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(Стр.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя параметра>" Тогда
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Если ТипЗнч(ЗначениеСтрокиДерева) = Тип("ОписаниеПараметровЗапроса")
			 Или ТипЗнч(ЗначениеСтрокиДерева) = Тип("ПараметрыАнализаДанных") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;

		ИначеЕсли ТипЗнч(ЗначениеСтрокиДерева) = Тип("ПараметрыМакетаТабличногоДокумента") Тогда
			Для Каждого Стр Из ЗначениеСтрокиДерева Цикл

			КонецЦикла;

		КонецЕсли;
	ИначеЕсли ИмяДляСравнения = "<имя документа>" Тогда
		Для Каждого ТекДок Из Метаданные.Документы Цикл
			ИменаСвойств.Добавить(ТекДок.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя справочника>" Тогда
		Для Каждого ТекДок Из Метаданные.Справочники Цикл
			ИменаСвойств.Добавить(ТекДок.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя предопределенного элемента справочника>"
			  Или ИмяДляСравнения = "<имя предопределенного счета>"
			  Или ИмяДляСравнения = "<имя предопределенного вида характеристик>"
			  Или ИмяДляСравнения = "<имя предопределенного объекта>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ИмяПредопределенного Из ОбъектМД.ПолучитьИменаПредопределенных() Цикл
			ИменаСвойств.Добавить(ИмяПредопределенного);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя реквизита>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		//TODO формы, Реквизиты Внешних Обработок и отчетов
		
		Для Каждого ТекЭлемент Из ОбъектМД.Реквизиты Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя табличной части>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ОбъектМД.ТабличныеЧасти Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя общего реквизита>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из Метаданные.ОбщиеРеквизиты Цикл
			ЭлементСостава = ТекЭлемент.Состав.Найти(ОбъектМД);
			Если ЭлементСостава = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			Если ЭлементСостава.Использование = Метаданные.СвойстваОбъектов.ИспользованиеОбщегоРеквизита.Авто
				 И ТекЭлемент.АвтоИспользование = Метаданные.СвойстваОбъектов.АвтоИспользованиеОбщегоРеквизита.Использовать Тогда
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			ИначеЕсли ЭлементСостава.Использование = Метаданные.СвойстваОбъектов.ИспользованиеОбщегоРеквизита.Использовать Тогда
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя константы>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.Константы Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя журнала документов>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ЖурналыДокументов Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя перечисления>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.Перечисления Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя значения>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Для Каждого ТекЭлемент Из ОбъектМД.ЗначенияПеречисления Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя отчета>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.Отчеты Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя обработки>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.Обработки Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя плана видов характеристик>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ПланыВидовХарактеристик Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя плана счетов>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ПланыСчетов Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя плана видов расчета>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ПланыВидовРасчета Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя регистра сведений>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.РегистрыСведений Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя регистра накопления>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.РегистрыНакопления Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя регистра бухгалтерии>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.РегистрыБухгалтерии Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя регистра расчета>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.РегистрыРасчета Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя бизнес-процесса>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.БизнесПроцессы Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя внешнего источника данных>" Тогда 
		Для Каждого ТекЭлемент Из Метаданные.ВнешниеИсточникиДанных Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя задачи>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.Задачи Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя последовательности>" Тогда 
		Для Каждого ТекЭлемент Из Метаданные.Последовательности Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя хранилища>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ХранилищаНастроек Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя плана обмена>" Тогда 
		Для Каждого ТекЭлемент Из Метаданные.ПланыОбмена Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя параметра сеанса>" Тогда 
		Для Каждого ТекЭлемент Из Метаданные.ПараметрыСеанса Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя ws-ссылки>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.WSСсылки Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	 
	ИначеЕсли ИмяДляСравнения = "<имя реквизита адресации>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Если Метаданные.БизнесПроцессы.Содержит(ОбъектМД) Тогда
			Для Каждого ТекЭлемент Из ОбъектМД.Задача.РеквизитыАдресации Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		Иначе

			Для Каждого ТекЭлемент Из ОбъектМД.РеквизитыАдресации Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		КонецЕсли;
		
	ИначеЕсли ИмяДляСравнения = "<имя измерения>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		ЭтоРегистрБухгалтерии = Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМД);

		Для Каждого ТекЭлемент Из ОбъектМД.Измерения Цикл
			Если ЭтоРегистрБухгалтерии Тогда
				Если Не ТекЭлемент.Балансовый тогда
					Продолжить;
				КонецЕсли;
			КонецЕсли;
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя ресурса>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		ЭтоРегистрБухгалтерии = Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМД);

		Для Каждого ТекЭлемент Из ОбъектМД.Ресурсы Цикл
			ЭтоДтКт = Ложь;
			Если ЭтоРегистрБухгалтерии Тогда
				Если Не ТекЭлемент.Балансовый тогда
					ЭтоДтКт = Истина;
				КонецЕсли;
			КонецЕсли;
			
			Если ЭтоДтКт Тогда
				ИменаСвойств.Добавить(ТекЭлемент.Имя+"Дт");
				ИменаСвойств.Добавить(ТекЭлемент.Имя+"Кт");
			Иначе
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя признака учета>" Тогда
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Для Каждого ТекЭлемент Из ОбъектМД.ПризнакиУчета Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя флага учета субконто>" Тогда	 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Для Каждого ТекЭлемент Из ОбъектМД.ПризнакиУчетаСубконто Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя измерения>кт" Тогда 	
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Для Каждого ТекЭлемент Из ОбъектМД.Измерения Цикл
			Если ТекЭлемент.Балансовый Тогда
				Продолжить;
			КонецЕсли;
			ИменаСвойств.Добавить(ТекЭлемент.Имя+"Кт");
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя измерения>дт" Тогда 	
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;

		Для Каждого ТекЭлемент Из ОбъектМД.Измерения Цикл
			Если ТекЭлемент.Балансовый Тогда
				Продолжить;
			КонецЕсли;
			ИменаСвойств.Добавить(ТекЭлемент.Имя+"Дт");
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя стиля>" Тогда 	
		Для Каждого ТекЭлемент Из Метаданные.Стили Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя перерасчета>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
//		пер = РегистрыРасчета._ДемоОсновныеНачисления.Перерасчеты.ПерерасчетОсновныхНачислений
		Для Каждого ТекЭлемент Из ОбъектМД.Перерасчеты Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя критерия отбора>" Тогда 
		Для Каждого ТекЭлемент Из Метаданные.КритерииОтбора Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя сервиса интеграции>" Тогда 
		//@skip-check bsl-legacy-check-static-feature-access-for-unknown-left-part
		Для Каждого ТекЭлемент Из Метаданные.СервисыИнтеграции Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя источника>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя макета>" Тогда 
		Для Каждого ТекЭлемент Из БиблиотекаМакетовОформленияКомпоновкиДанных Цикл
			Если ИменаСвойств.Найти(ТекЭлемент.Имя) = Неопределено Тогда
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя таблицы измерения>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ОбъектМД.ТаблицыИзмерений Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя куба>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ОбъектМД.Кубы Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя таблицы>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ОбъектМД.Таблицы Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя элемента схемы>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя элемента>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(Строка(ТекЭлемент.Значение));
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя слоя>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя серии>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя графы>" Тогда 
		Если ОбъектМД = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ОбъектМД.Графы Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
		
	ИначеЕсли ИмяДляСравнения = "<имя регистра>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Метаданные().Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя элемента отбора>" Тогда 
		Если ЗначениеСтрокиДерева = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя колонки>" Тогда
		ТипЗначенияЗначения = ТипЗнч(ЗначениеСтрокиДерева);
		Если ОписаниеТипаПлатформы.Имя = "Строка табличной части" Тогда
			Для Каждого ТекЭлемент ИЗ ОбъектМД.Реквизиты Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		ИначеЕсли ТипЗначенияЗначения = Тип("КоллекцияКолонокТаблицыЗначений")
			 Или ТипЗначенияЗначения = Тип("КоллекцияКолонокРезультатаЗапроса")
			 Или ТипЗначенияЗначения = Тип("КоллекцияКолонокДереваЗначений")
			 Или ТипЗначенияЗначения = Тип("КолонкиВременнойТаблицыЗапроса")
			 Или ТипЗначенияЗначения = Тип("КолонкиОписанияИсточникаДанных") 
			 Или ТипЗначенияЗначения = Тип("КолонкиСписка") 
			 Или ТипЗначенияЗначения = Тип("КолонкиАнализаДанных") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		ИначеЕсли ТипЗначенияЗначения = Тип("СтрокаТаблицыЗначений")
				  Или ТипЗначенияЗначения = Тип("СтрокаДереваЗначений") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева.Владелец().Колонки Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		ИначеЕсли УИ_ОбщегоНазначенияКлиентСервер.ВерсияПлатформыНеМладше("8.3.21") Тогда
			//@skip-check bsl-legacy-check-string-literal
			Если ТипЗначенияЗначения = Тип("КолонкиДанныхДиаграммыГанта")
				 Или ТипЗначенияЗначения = Тип("ДанныеЗначенияДиаграммыГанта") Тогда
				Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
					ИменаСвойств.Добавить(ТекЭлемент.Имя);
				КонецЦикла;
			КонецЕсли;
		Иначе
			УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтрШаблон("Не реализовано чтение динамического свойство типа %1. Напишите заявку разработчику",
																		   ИмяСвойства));
			Сообщить(ИмяСвойства);

		КонецЕсли;
//	ИначеЕсли ИмяДляСравнения = "<имя элемента управления>" Тогда
//		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
//			ИменаСвойств.Добавить(ТекЭлемент.Имя);
//		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя индекса>" Тогда
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя свойства>" Тогда
		Если ТипЗнч(ЗначениеСтрокиДерева) = Тип("ОбъектXDTO") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева.Свойства() Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		Иначе
			УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтрШаблон("Получение свойств для типа %1 не реализовано.",
																		   ОписаниеТипаПлатформы.Имя));
		КонецЕсли;
	ИначеЕсли ИмяДляСравнения = "<имя поля>" Тогда 
		ТипЗначенияЗначения = ТипЗнч(ЗначениеСтрокиДерева);
		
		Если ТипЗначенияЗначения = Тип("ВыборкаИзРезультатаЗапроса") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева.Владелец().Колонки Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		ИначеЕсли ТипЗначенияЗначения = Тип("КоллекцияПолейXBase") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		ИначеЕсли ТипЗначенияЗначения = Тип("XBase") Тогда
			Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева.Поля Цикл
				ИменаСвойств.Добавить(ТекЭлемент.Имя);
			КонецЦикла;
		КонецЕсли;
//	ИначеЕсли ИмяДляСравнения = "<имя колонки прогноза>" Тогда
//		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
//			ИменаСвойств.Добавить(ТекЭлемент.Имя);
//		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя точки маршрута бизнес-процесса>" Тогда 
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя варианта>" Тогда 
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(Строка(ТекЭлемент));
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя объекта описания метаданного>" Тогда 
		Для Каждого ТекЭлемент Из ЗначениеСтрокиДерева Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	ИначеЕсли ИмяДляСравнения = "<имя картинки>" Тогда
		Для Каждого ТекЭлемент Из Метаданные.ОбщиеКартинки Цикл
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла; 
	ИначеЕсли ИмяДляСравнения = "<имя элемента стиля>" Тогда 
		ВидДляФильтра = Неопределено;
		Если Нрег(ОписаниеТипаПлатформы.Имя) = "цветастиля" Тогда
			ВидДляФильтра = Метаданные.СвойстваОбъектов.ВидЭлементаСтиля.Цвет;
		ИначеЕсли Нрег(ОписаниеТипаПлатформы.Имя) = "рамкистиля" Тогда
			ВидДляФильтра = Метаданные.СвойстваОбъектов.ВидЭлементаСтиля.Рамка;
		ИначеЕсли Нрег(ОписаниеТипаПлатформы.Имя) = "шрифтыстиля" Тогда
			ВидДляФильтра = Метаданные.СвойстваОбъектов.ВидЭлементаСтиля.Шрифт;
		КонецЕсли;
		
		Если ВидДляФильтра = Неопределено Тогда
			Возврат;
		КонецЕсли;
		Для Каждого ТекЭлемент Из Метаданные.ЭлементыСтиля Цикл
			Если ТекЭлемент.Вид <> ВидДляФильтра Тогда
				Продолжить;
			КонецЕсли;
			ИменаСвойств.Добавить(ТекЭлемент.Имя);
		КонецЦикла;
	Иначе
		УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтрШаблон("Не реализовано чтение динамического свойство типа %1. Напишите заявку разработчику",
																	   ИмяСвойства));
		Сообщить(ИмяСвойства);
	КонецЕсли;
КонецПроцедуры

// Имена свойств описания типа платформы.
// 
// Параметры:
//  ОписаниеТипаПлатформы- см. УИ_ТипыПлатформыКлиентСервер.НовыйОписаниеТипаПлатформы
//  Значение - Произвольный
//  ОбъектМД - ОбъектМетаданных
// 
// Возвращаемое значение:
//  Массив Из Строка
Функция ИменаСвойствОписанияТипаПлатформы(ОписаниеТипаПлатформы, Значение, ОбъектМД) Экспорт
	ВерсияПлатформы = УИ_ОбщегоНазначенияКлиентСервер.ТекущаяВерсияПлатформы1СПредприятияЧислом();
		
	ИменаСвойств = Новый Массив;//Массив из Строка
	Для Каждого ТекСвойство Из ОписаниеТипаПлатформы.Свойства Цикл
		Если ТекСвойство.МинимальнаяПлатформа > ВерсияПлатформы Тогда
			Продолжить;
		КонецЕсли;
		Если СтрНайти(ТекСвойство.Имя, "<") > 0 Тогда
			ЗаполнитьДинамическиеСвойстваЗначения(ОписаниеТипаПлатформы, ТекСвойство.Имя, ИменаСвойств, Значение, ОбъектМД);
		Иначе
			ИменаСвойств.Добавить(ТекСвойство.Имя);
		КонецЕсли;
	КонецЦикла;	
	
	Возврат ИменаСвойств;
КонецФункции


// Описание типа объекта метаданных.
// 
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - Объект метаданных
// 
// Возвращаемое значение:
//  см. УИ_ТипыПлатформыКлиентСервер.НовыйОписаниеТипаПлатформы
// Возвращаемое значение:
// 	Неопределено - описание типа не найдено
Функция ОписаниеТипаОбъектаМетаданных(ОбъектМетаданных) Экспорт
	Если ТипЗнч(ОбъектМетаданных) <> Тип("ОбъектМетаданных") Тогда
		Возврат Неопределено;
	КонецЕсли;

	ПолноеИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя();

	МассивФрагментов = СтрРазделить(ПолноеИмяОбъектаМетаданных, ".");
			// Исключения из общего правила
	Если МассивФрагментов[0] = "ОбщаяФорма" Тогда
		МассивФрагментов[0] = "Форма";
	ИначеЕсли МассивФрагментов[0] = "ОбщийМакет" Тогда
		МассивФрагментов[0] = "Макет";
	КонецЕсли;
	ИмяТипа = "ОбъектМетаданных" + МассивФрагментов[МассивФрагментов.ВГраница() - 1];

	Возврат УИ_ТипыПлатформыКлиентСервер.ОписаниеТипаПлатформыПоИмени(ИмяТипа);

КонецФункции

#КонецОбласти
#Область СравнениеОбъектов

Процедура ДобавитьОбъектВМассивОбъектовКСравнению(МассивОБъектов, СсылкаНаОбъект)
	Если МассивОБъектов.Найти(СсылкаНаОбъект) = Неопределено Тогда
		МассивОБъектов.Добавить(СсылкаНаОбъект);
	КонецЕсли;
КонецПроцедуры

Функция КлючНастроекОбъектовКСравнению() Экспорт
	Возврат "ОбъектыКСравнению";
КонецФункции

Процедура ДобавитьМассивОбъектовКСравнению(Объекты) Экспорт
	МассивОбъектовКСравнению=ОбъектыДобавленныеКСравнению();

	Если ТипЗнч(Объекты) = Тип("Массив") Тогда
		Для Каждого Эл Из Объекты Цикл
			ДобавитьОбъектВМассивОбъектовКСравнению(МассивОбъектовКСравнению, Эл);
		КонецЦикла;
	ИначеЕсли ТипЗнч(Объекты) = Тип("СписокЗначений") Тогда
		Для Каждого Эл Из Объекты Цикл
			ДобавитьОбъектВМассивОбъектовКСравнению(МассивОбъектовКСравнению, Эл.Значение);
		КонецЦикла;
	Иначе
		ДобавитьОбъектВМассивОбъектовКСравнению(МассивОбъектовКСравнению, Объекты);
	КонецЕсли;

	УИ_ОбщегоНазначения.ХранилищеСистемныхНастроекСохранить(
		УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек(), КлючНастроекОбъектовКСравнению(),
		МассивОбъектовКСравнению);

КонецПроцедуры

Функция ОбъектыДобавленныеКСравнению() Экспорт
	КлючОбъекта=УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек();
	КлючНастроек=КлючНастроекОбъектовКСравнению();

	МассивОбъектовКСравнению=ХранилищеСистемныхНастроекЗагрузить(КлючОбъекта, КлючНастроек, , , ИмяПользователя());
	Если МассивОбъектовКСравнению = Неопределено Тогда
		МассивОбъектовКСравнению=Новый Массив;
	КонецЕсли;

	Возврат МассивОбъектовКСравнению;
КонецФункции

Процедура ОчиститьОбъектыДобавленныеКСравнению() Экспорт
	УИ_ОбщегоНазначения.ХранилищеСистемныхНастроекСохранить(
		УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек(), КлючНастроекОбъектовКСравнению(), Новый Массив);
КонецПроцедуры

#КонецОбласти

#Область НастройкаОтладкаДополнительныхОтчетовИОбработок

Функция КлючНастроекОтладкиДополнительныхОтчетовИОбработок() Экспорт
	Возврат "НастройкиОтладкиДополнительныхОтчетовИОбработок";
КонецФункции

Функция НовыйСтруктураНастройкиОтладкиДополнительнойОбработки() Экспорт
	Структура=Новый Структура;
	Структура.Вставить("ОтладкаВключена", Ложь);
	Структура.Вставить("ИмяФайлаНаСервере", "");
	Структура.Вставить("Пользователь", Неопределено);

	Возврат Структура;
КонецФункции

Функция НастройкиОтладкиДополнительнойОбработки(ДополнительнаяОбработка) Экспорт
	КлючОбъекта=УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек();
	КлючНастроек=КлючНастроекОтладкиДополнительныхОтчетовИОбработок();

	СоответствиеНастроек=ХранилищеСистемныхНастроекЗагрузить(КлючОбъекта, КлючНастроек);
	Если СоответствиеНастроек = Неопределено Тогда
		СоответствиеНастроек=Новый Соответствие;
	КонецЕсли;

	СтруктураНастройки=НовыйСтруктураНастройкиОтладкиДополнительнойОбработки();
	СохраненнаяНастройка=СоответствиеНастроек[ДополнительнаяОбработка];
	Если СохраненнаяНастройка <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(СтруктураНастройки, СохраненнаяНастройка);
	КонецЕсли;

	Возврат СтруктураНастройки;
КонецФункции

Процедура ЗаписатьНастройкиОтладкиДополнительнойОбработки(ДополнительнаяОбработка, Настройки) Экспорт
	КлючОбъекта=УИ_ОбщегоНазначенияКлиентСервер.КлючОбъектаВХранилищеНастроек();
	КлючНастроек=КлючНастроекОтладкиДополнительныхОтчетовИОбработок();

	СоответствиеНастроек=ХранилищеСистемныхНастроекЗагрузить(КлючОбъекта, КлючНастроек);
	Если СоответствиеНастроек = Неопределено Тогда
		СоответствиеНастроек=Новый Соответствие;
	КонецЕсли;

	СоответствиеНастроек.Вставить(ДополнительнаяОбработка, Настройки);

	УИ_ОбщегоНазначения.ХранилищеСистемныхНастроекСохранить(
		КлючОбъекта, КлючНастроек, СоответствиеНастроек);

КонецПроцедуры

#КонецОбласти

#Область ДанныеВБазе

////////////////////////////////////////////////////////////////////////////////
// Общие процедуры и функции для работы с данными в базе.

// Производит замену ссылок во всех данных. После замены неиспользуемые ссылки опционально удаляются.
// Замена ссылок происходит с транзакциями по изменяемому объекту и его связям, не по анализируемой ссылке.
// При вызове в неразделенном сеансе не выявляет ссылок в разделенных областях.
//
// Параметры:
//   ПарыЗамен - Соответствие - пары замен.
//       * Ключ     - ЛюбаяСсылка - что ищем (дубль).
//       * Значение - ЛюбаяСсылка - на что заменяем (оригинал).
//       Ссылки сами на себя и пустые ссылки для поиска будут проигнорированы.
//   
//   Параметры - Структура - Необязательный. Параметры замены.
//       
//       * СпособУдаления - Строка - необязательный. Что делать с дублем после успешной замены.
//           ""                - по умолчанию. Не предпринимать никаких действий.
//           "Пометка"         - помечать на удаление.
//           "Непосредственно" - удалять непосредственно.
//       
//       * УчитыватьПрикладныеПравила - Булево - необязательный. Режим проверки параметра ПарыЗамен.
//           Истина - по умолчанию. Проверять каждую пару "дубль-оригинал" (вызывается функция
//                    ВозможностьЗаменыЭлементов модуля менеджера).
//           Ложь   - отключить прикладные проверки пар.
//       
//       * ПараметрыЗаписи.ЗаписьВРежимеЗагрузки  - Булево - необязательный. Режим записи мест использования при замене дублей на оригиналы.
//           Истина - по умолчанию. Места использования дублей записываются в режиме ОбменДанными.Загрузка = Ложь.
//           Ложь   - запись ведется в режиме ОбменДанными.Загрузка = Истина.
//       
//       * ЗаменаПарыВТранзакции - Булево - необязательный. Определяет размер транзакции.
//           Истина - по умолчанию. Транзакция охватывает все места использования одного дубля. Может быть очень ресурсоемко 
//                    в случае большого количества мест использований.
//           Ложь   - замена каждого места использования выполняется в отдельной транзакции.
//       
//       * ПараметрыЗаписи.ПривилегированныйРежим - Булево - необязательный. Требуется ли устанавливать привилегированный режим перед запись.
//           Ложь   - по умолчанию. Записывать с текущими правами.
//           Истина - записывать в привилегированном режиме.
//
// Возвращаемое значение:
//   ТаблицаЗначений - неуспешные замены (ошибки).
//       * Ссылка - ЛюбаяСсылка - ссылка, которую заменяли.
//       * ОбъектОшибки - Произвольный - объект - причина ошибки.
//       * ПредставлениеОбъектаОшибки - Строка - строковое представление объекта ошибки.
//       * ТипОшибки - Строка - тип ошибки:
//           "ОшибкаБлокировки"  - при обработке ссылки некоторые объекты были заблокированы.
//           "ДанныеИзменены"    - в процессе обработки данные были изменены другим пользователем.
//           "ОшибкаЗаписи"      - не смогли записать объект, или метод ВозможностьЗаменыЭлементов вернул отказ.
//           "ОшибкаУдаления"    - не смогли удалить объект.
//           "НеизвестныеДанные" - при обработке были найдены данные, которые не планировались к анализу, замена не реализована.
//       * ТекстОшибки - Строка - подробное описание ошибки.
//
Функция ЗаменитьСсылки(Знач ПарыЗамен, Знач Параметры = Неопределено) Экспорт

	ТипСтрока = Новый ОписаниеТипов("Строка");

	ОшибкиЗамены = Новый ТаблицаЗначений;
	ОшибкиЗамены.Колонки.Добавить("Ссылка");
	ОшибкиЗамены.Колонки.Добавить("ОбъектОшибки");
	ОшибкиЗамены.Колонки.Добавить("ПредставлениеОбъектаОшибки", ТипСтрока);
	ОшибкиЗамены.Колонки.Добавить("ТипОшибки", ТипСтрока);
	ОшибкиЗамены.Колонки.Добавить("ТекстОшибки", ТипСтрока);

	ОшибкиЗамены.Индексы.Добавить("Ссылка");
	ОшибкиЗамены.Индексы.Добавить("Ссылка, ОбъектОшибки, ТипОшибки");

	Результат = Новый Структура;
	Результат.Вставить("ЕстьОшибки", Ложь);
	Результат.Вставить("Ошибки", ОшибкиЗамены);
	
	// Значения по умолчанию.
	ПараметрыВыполнения = Новый Структура;
	ПараметрыВыполнения.Вставить("УдалятьНепосредственно", Ложь);
	ПараметрыВыполнения.Вставить("ПомечатьНаУдаление", Ложь);
	ПараметрыВыполнения.Вставить("УчитыватьПрикладныеПравила", Ложь);
	ЗаменаПарыВТранзакции = Истина;

	ПараметрыЗаписи=УИ_ОбщегоНазначенияКлиентСервер.СтруктураПараметровЗаписиПоУмолчанию();
	
	// Переданные значения.
	ЗначениеПараметра = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "СпособУдаления");
	Если ЗначениеПараметра = "Непосредственно" Тогда
		ПараметрыВыполнения.УдалятьНепосредственно = Истина;
		ПараметрыВыполнения.ПомечатьНаУдаление     = Ложь;
	ИначеЕсли ЗначениеПараметра = "Пометка" Тогда
		ПараметрыВыполнения.УдалятьНепосредственно = Ложь;
		ПараметрыВыполнения.ПомечатьНаУдаление     = Истина;
	КонецЕсли;

	ЗначениеПараметра = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "ЗаменаПарыВТранзакции");
	Если ТипЗнч(ЗначениеПараметра) = Тип("Булево") Тогда
		ЗаменаПарыВТранзакции = ЗначениеПараметра;
	КонецЕсли;

	ЗначениеПараметра = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "УчитыватьПрикладныеПравила");
	Если ТипЗнч(ЗначениеПараметра) = Тип("Булево") Тогда
		ПараметрыВыполнения.УчитыватьПрикладныеПравила = ЗначениеПараметра;
	КонецЕсли;

	ЗначениеПараметра = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Параметры, "ПараметрыЗаписи");
	Если ТипЗнч(ЗначениеПараметра) = Тип("Структура") Тогда
		ЗаполнитьЗначенияСвойств(ПараметрыЗаписи, ЗначениеПараметра);
	КонецЕсли;
	ПараметрыВыполнения.Вставить("ПараметрыЗаписи", ПараметрыЗаписи);
	Если ПарыЗамен.Количество() = 0 Тогда
		Возврат Результат.Ошибки;
	КонецЕсли;

	Дубли = Новый Массив;
	Для Каждого КлючЗначение Из ПарыЗамен Цикл
		Дубль = КлючЗначение.Ключ;
		Оригинал = КлючЗначение.Значение;
		Если Дубль = Оригинал Или Дубль.Пустая() Тогда
			Продолжить; // Самого на себя и пустые ссылки не заменяем.
		КонецЕсли;
		Дубли.Добавить(Дубль);
		// Пропускаем промежуточные замены, чтобы не строить граф (если A->B и B->C то вместо A->B производится замена A->C).
		ОригиналОригинала = ПарыЗамен[Оригинал];
		ЕстьОригиналОригинала = (ОригиналОригинала <> Неопределено И ОригиналОригинала <> Дубль И ОригиналОригинала
			<> Оригинал);
		Если ЕстьОригиналОригинала Тогда
			Пока ЕстьОригиналОригинала Цикл
				Оригинал = ОригиналОригинала;
				ОригиналОригинала = ПарыЗамен[Оригинал];
				ЕстьОригиналОригинала = (ОригиналОригинала <> Неопределено И ОригиналОригинала <> Дубль
					И ОригиналОригинала <> Оригинал);
			КонецЦикла;
			ПарыЗамен.Вставить(Дубль, Оригинал);
		КонецЕсли;
	КонецЦикла;

//	Если ПараметрыВыполнения.УчитыватьПрикладныеПравила И ПодсистемаСуществует(
//		"СтандартныеПодсистемы.ПоискИУдалениеДублей") Тогда
//		МодульПоискИУдалениеДублей = ОбщийМодуль("ПоискИУдалениеДублей");
//		Ошибки = МодульПоискИУдалениеДублей.ПроверитьВозможностьЗаменыЭлементов(ПарыЗамен, Параметры);
//		Для Каждого КлючЗначение Из Ошибки Цикл
//			Дубль = КлючЗначение.Ключ;
//			Оригинал = ПарыЗамен[Дубль];
//			ТекстОшибки = КлючЗначение.Значение;
//			Причина = ОписаниеОшибкиЗамены("ОшибкаЗаписи", Оригинал, ПредметСтрокой(Оригинал), ТекстОшибки);
//			ЗарегистрироватьОшибкуЗамены(Результат, Дубль, Причина);
//
//			Индекс = Дубли.Найти(Дубль);
//			Если Индекс <> Неопределено Тогда
//				Дубли.Удалить(Индекс); // пропускаем проблемный элемент.
//			КонецЕсли;
//		КонецЦикла;
//	КонецЕсли;

	ТаблицаПоиска = МестаИспользования(Дубли);
	
	// Для каждой ссылки объекта будем производить замены в порядке "Константа", "Объект", "Набор".
	// Одновременно пустая строка в этой колонке - флаг того, что эта замена не нужна или уже была произведена.
	ТаблицаПоиска.Колонки.Добавить("КлючЗамены", ТипСтрока);
	ТаблицаПоиска.Индексы.Добавить("Ссылка, КлючЗамены");
	ТаблицаПоиска.Индексы.Добавить("Данные, КлючЗамены");
	
	// Вспомогательные данные
	ТаблицаПоиска.Колонки.Добавить("ЦелеваяСсылка");
	ТаблицаПоиска.Колонки.Добавить("Обработано", Новый ОписаниеТипов("Булево"));
	
	// Определяем порядок обработки и проверяем то, что мы можем обработать.
	Количество = Дубли.Количество();
	Для Номер = 1 По Количество Цикл
		ОбратныйИндекс = Количество - Номер;
		Дубль = Дубли[ОбратныйИндекс];
		РезультатРазметки = РазметитьМестаИспользования(ПараметрыВыполнения, Дубль, ПарыЗамен[Дубль], ТаблицаПоиска);
		Если Не РезультатРазметки.Успех Тогда
			// Найдены неизвестные типы замены, не будем работать с этой ссылкой, возможно нарушение связности.
			Дубли.Удалить(ОбратныйИндекс);
			Для Каждого Ошибка Из РезультатРазметки.ОшибкиРазметки Цикл
				ПредставлениеОбъектаОшибки = ПредметСтрокой(Ошибка.Объект);
				ЗарегистрироватьОшибкуЗамены(Результат, Дубль, ОписаниеОшибкиЗамены("НеизвестныеДанные", Ошибка.Объект,
					ПредставлениеОбъектаОшибки, Ошибка.Текст));
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;

	ПараметрыВыполнения.Вставить("ПарыЗамен", ПарыЗамен);
	ПараметрыВыполнения.Вставить("УспешныеЗамены", Новый Соответствие);

//	Если ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
//		МодульУправлениеДоступом = ОбщийМодуль("УправлениеДоступом");
//		МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Истина);
//	КонецЕсли;

	Попытка
		Если ЗаменаПарыВТранзакции Тогда
			Для Каждого Дубль Из Дубли Цикл
				ЗаменитьСсылкуОднойТранзакцией(Результат, Дубль, ПараметрыВыполнения, ТаблицаПоиска);
			КонецЦикла;
		Иначе
			ЗаменитьСсылкиКороткимиТранзакциями(Результат, ПараметрыВыполнения, Дубли, ТаблицаПоиска);
		КонецЕсли;

//		Если ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
//			МодульУправлениеДоступом = ОбщийМодуль("УправлениеДоступом");
//			МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
//		КонецЕсли;

	Исключение
//		Если ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
//			МодульУправлениеДоступом = ОбщийМодуль("УправлениеДоступом");
//			МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Ложь);
//		КонецЕсли;
		ВызватьИсключение;
	КонецПопытки;

	Возврат Результат.Ошибки;
КонецФункции

// Получает все места использования ссылок.
// Если какая-либо ссылка нигде не используется, то строк для нее в результирующей таблице не будет.
// При вызове в неразделенном сеансе не выявляет ссылок в разделенных областях.
//
// Параметры:
//     НаборСсылок     - Массив - ссылки, для которых ищем места использования.
//     АдресРезультата - Строка - необязательный адрес во временном хранилище, куда будет помещен копия результата
//                                замены.
// 
// Возвращаемое значение:
//     ТаблицаЗначений - состоит из колонок:
//       * Ссылка - ЛюбаяСсылка - ссылка, которая анализируется.
//       * Данные - Произвольный - данные, содержащие анализируемую ссылку.
//       * Метаданные - ОбъектМетаданных - метаданные найденных данных.
//       * ПредставлениеДанных - Строка - представление данных, содержащих анализируемую ссылку.
//       * ТипСсылки - Тип - тип анализируемой ссылки.
//       * ВспомогательныеДанные - Булево - Истина, если данные используются анализируемой ссылкой как
//           вспомогательные данные (ведущее измерение или попали в исключение ПриДобавленииИсключенийПоискаСсылок).
//       * ЭтоСлужебныеДанные - Булево - данные попали в исключение ПриДобавленииИсключенийПоискаСсылок
//
Функция МестаИспользования(Знач НаборСсылок, Знач АдресРезультата = "") Экспорт

	МестаИспользования = Новый ТаблицаЗначений;

	УстановитьПривилегированныйРежим(Истина);
	МестаИспользования = НайтиПоСсылкам(НаборСсылок);
	УстановитьПривилегированныйРежим(Ложь);
	
	// МестаИспользования - ТаблицаЗначений - где:
	// * Ссылка - ЛюбаяСсылка - Ссылка, которая анализируется.
	// * Данные - Произвольный - Данные, содержащие анализируемую ссылку.
	// * Метаданные - ОбъектМетаданных - Метаданные найденных данных.

	МестаИспользования.Колонки.Добавить("ПредставлениеДанных", Новый ОписаниеТипов("Строка"));
	МестаИспользования.Колонки.Добавить("ТипСсылки");
	МестаИспользования.Колонки.Добавить("ИнформацияОМестеИспользования");
	МестаИспользования.Колонки.Добавить("ВспомогательныеДанные", Новый ОписаниеТипов("Булево"));
	МестаИспользования.Колонки.Добавить("ЭтоСлужебныеДанные", Новый ОписаниеТипов("Булево"));

	МестаИспользования.Индексы.Добавить("Ссылка");
	МестаИспользования.Индексы.Добавить("Данные");
	МестаИспользования.Индексы.Добавить("ВспомогательныеДанные");
	МестаИспользования.Индексы.Добавить("Ссылка, ВспомогательныеДанные");

	ТипКлючиЗаписей = ОписаниеТипаКлючиЗаписей();
	ТипВсеСсылки = ОписаниеТипаВсеСсылки();

	МетаданныеПоследовательностей = Метаданные.Последовательности;
	МетаданныеКонстант = Метаданные.Константы;
	МетаданныеДокументов = Метаданные.Документы;

	ИсключенияПоискаСсылок = ИсключенияПоискаСсылок();

	КэшИзмеренийРегистров = Новый Соответствие;

	Для Каждого МестоИспользования Из МестаИспользования Цикл
		ТипДанных = ТипЗнч(МестоИспользования.Данные);

		ЭтоСлужебныеДанные = ЭтоСлужебныеДанные(МестоИспользования, ИсключенияПоискаСсылок);
		ЭтоВспомогательныеДанные = ЭтоСлужебныеДанные;

		Если МетаданныеДокументов.Содержит(МестоИспользования.Метаданные) Тогда
			Представление = Строка(МестоИспользования.Данные);

		ИначеЕсли МетаданныеКонстант.Содержит(МестоИспользования.Метаданные) Тогда
			Представление = МестоИспользования.Метаданные.Представление() + " (" + НСтр("ru = 'константа'") + ")";

		ИначеЕсли МетаданныеПоследовательностей.Содержит(МестоИспользования.Метаданные) Тогда
			Представление = МестоИспользования.Метаданные.Представление() + " (" + НСтр("ru = 'последовательность'")
				+ ")";

		ИначеЕсли ТипДанных = Неопределено Тогда
			Представление = Строка(МестоИспользования.Данные);

		ИначеЕсли ТипВсеСсылки.СодержитТип(ТипДанных) Тогда
			МетаПредставлениеОбъекта = Новый Структура("ПредставлениеОбъекта");
			ЗаполнитьЗначенияСвойств(МетаПредставлениеОбъекта, МестоИспользования.Метаданные);
			Если ПустаяСтрока(МетаПредставлениеОбъекта.ПредставлениеОбъекта) Тогда
				МетаПредставление = МестоИспользования.Метаданные.Представление();
			Иначе
				МетаПредставление = МетаПредставлениеОбъекта.ПредставлениеОбъекта;
			КонецЕсли;
			Представление = Строка(МестоИспользования.Данные);
			Если Не ПустаяСтрока(МетаПредставление) Тогда
				Представление = Представление + " (" + МетаПредставление + ")";
			КонецЕсли;

		ИначеЕсли ТипКлючиЗаписей.СодержитТип(ТипДанных) Тогда
			Представление = МестоИспользования.Метаданные.ПредставлениеЗаписи;
			Если ПустаяСтрока(Представление) Тогда
				Представление = МестоИспользования.Метаданные.Представление();
			КонецЕсли;

			ОписаниеИзмерений = "";
			Для Каждого КлючЗначение Из ОписаниеИзмеренийНабора(МестоИспользования.Метаданные, КэшИзмеренийРегистров) Цикл
				Значение = МестоИспользования.Данные[КлючЗначение.Ключ];
				Описание = КлючЗначение.Значение;
				Если МестоИспользования.Ссылка = Значение Тогда
					Если Описание.Ведущее Тогда
						ЭтоВспомогательныеДанные = Истина;
					КонецЕсли;
				КонецЕсли;
				ФорматЗначения = Описание.Формат;
				ОписаниеИзмерений = ОписаниеИзмерений + ", " + Описание.Представление + " """ + ?(ФорматЗначения
					= Неопределено, Строка(Значение), Формат(Значение, ФорматЗначения)) + """";
			КонецЦикла;

			ОписаниеИзмерений = Сред(ОписаниеИзмерений, 3);
			Если Не ПустаяСтрока(ОписаниеИзмерений) Тогда
				Представление = Представление + " (" + ОписаниеИзмерений + ")";
			КонецЕсли;

		Иначе
			Представление = Строка(МестоИспользования.Данные);

		КонецЕсли;

		МестоИспользования.ПредставлениеДанных = Представление;
		МестоИспользования.ВспомогательныеДанные = ЭтоВспомогательныеДанные;
		МестоИспользования.ЭтоСлужебныеДанные = ЭтоСлужебныеДанные;
		МестоИспользования.ТипСсылки = ТипЗнч(МестоИспользования.Ссылка);
	КонецЦикла;

	Если Не ПустаяСтрока(АдресРезультата) Тогда
		ПоместитьВоВременноеХранилище(МестаИспользования, АдресРезультата);
	КонецЕсли;

	Возврат МестаИспользования;
КонецФункции

#КонецОбласти

#Область ВнешниеКомпоненты

// Проверка существования макета по метаданным конфигурации и расширений.
//
// Параметры:
//  ПолноеИмяМакета - Строка - полное имя макета.
//
// Возвращаемое значение:
//  Булево - признак существования макета.
//
Функция МакетСуществует(ПолноеИмяМакета)

	Макет = Метаданные.НайтиПоПолномуИмени(ПолноеИмяМакета);
	Если ТипЗнч(Макет) = Тип("ОбъектМетаданных") Тогда

		Шаблон = Новый Структура("ТипМакета");
		ЗаполнитьЗначенияСвойств(Шаблон, Макет);
		ТипМакета = Неопределено;
		Если Шаблон.Свойство("ТипМакета", ТипМакета) Тогда
			Возврат ТипМакета <> Неопределено;
		КонецЕсли;

	КонецЕсли;

	Возврат Ложь;

КонецФункции

#КонецОбласти

#Область МестаИспользования

Функция ОписаниеТипаКлючиЗаписей()

	ДобавляемыеТипы = Новый Массив;
	Для Каждого Мета Из Метаданные.РегистрыСведений Цикл
		ДобавляемыеТипы.Добавить(Тип("РегистрСведенийКлючЗаписи." + Мета.Имя));
	КонецЦикла;
	Для Каждого Мета Из Метаданные.РегистрыНакопления Цикл
		ДобавляемыеТипы.Добавить(Тип("РегистрНакопленияКлючЗаписи." + Мета.Имя));
	КонецЦикла;
	Для Каждого Мета Из Метаданные.РегистрыБухгалтерии Цикл
		ДобавляемыеТипы.Добавить(Тип("РегистрБухгалтерииКлючЗаписи." + Мета.Имя));
	КонецЦикла;
	Для Каждого Мета Из Метаданные.РегистрыРасчета Цикл
		ДобавляемыеТипы.Добавить(Тип("РегистрРасчетаКлючЗаписи." + Мета.Имя));
	КонецЦикла;

	Возврат Новый ОписаниеТипов(ДобавляемыеТипы);
КонецФункции

Функция ОписаниеИзмеренийНабора(Знач МетаданныеРегистра, КэшИзмеренийРегистров)

	ОписаниеИзмерений = КэшИзмеренийРегистров[МетаданныеРегистра];
	Если ОписаниеИзмерений <> Неопределено Тогда
		Возврат ОписаниеИзмерений;
	КонецЕсли;
	
	// Период и регистратор, если есть.
	ОписаниеИзмерений = Новый Структура;

	ДанныеИзмерения = Новый Структура("Ведущее, Представление, Формат, Тип", Ложь);

	Если Метаданные.РегистрыСведений.Содержит(МетаданныеРегистра) Тогда
		// Возможно есть период
		МетаПериод = МетаданныеРегистра.ПериодичностьРегистраСведений;
		Периодичность = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений;

		Если МетаПериод = Периодичность.ПозицияРегистратора Тогда
			ДанныеИзмерения.Тип           = Документы.ТипВсеСсылки();
			ДанныеИзмерения.Представление = НСтр("ru='Регистратор'");
			ДанныеИзмерения.Ведущее       = Истина;
			ОписаниеИзмерений.Вставить("Регистратор", ДанныеИзмерения);

		ИначеЕсли МетаПериод = Периодичность.Год Тогда
			ДанныеИзмерения.Тип           = Новый ОписаниеТипов("Дата");
			ДанныеИзмерения.Представление = НСтр("ru='Период'");
			ДанныеИзмерения.Формат        = НСтр("ru = 'ДФ=''yyyy ""г.""''; ДП=''Дата не задана'''");
			ОписаниеИзмерений.Вставить("Период", ДанныеИзмерения);

		ИначеЕсли МетаПериод = Периодичность.День Тогда
			ДанныеИзмерения.Тип           = Новый ОписаниеТипов("Дата");
			ДанныеИзмерения.Представление = НСтр("ru='Период'");
			ДанныеИзмерения.Формат        = НСтр("ru = 'ДЛФ=D; ДП=''Дата не задана'''");
			ОписаниеИзмерений.Вставить("Период", ДанныеИзмерения);

		ИначеЕсли МетаПериод = Периодичность.Квартал Тогда
			ДанныеИзмерения.Тип           = Новый ОписаниеТипов("Дата");
			ДанныеИзмерения.Представление = НСтр("ru='Период'");
			ДанныеИзмерения.Формат        =  НСтр(
				"ru = 'ДФ=''к """"квартал """"yyyy """"г.""""''; ДП=''Дата не задана'''");
			ОписаниеИзмерений.Вставить("Период", ДанныеИзмерения);

		ИначеЕсли МетаПериод = Периодичность.Месяц Тогда
			ДанныеИзмерения.Тип           = Новый ОписаниеТипов("Дата");
			ДанныеИзмерения.Представление = НСтр("ru='Период'");
			ДанныеИзмерения.Формат        = НСтр("ru = 'ДФ=''ММММ yyyy """"г.""""''; ДП=''Дата не задана'''");
			ОписаниеИзмерений.Вставить("Период", ДанныеИзмерения);

		ИначеЕсли МетаПериод = Периодичность.Секунда Тогда
			ДанныеИзмерения.Тип           = Новый ОписаниеТипов("Дата");
			ДанныеИзмерения.Представление = НСтр("ru='Период'");
			ДанныеИзмерения.Формат        = НСтр("ru = 'ДЛФ=DT; ДП=''Дата не задана'''");
			ОписаниеИзмерений.Вставить("Период", ДанныеИзмерения);

		КонецЕсли;

	Иначе
		ДанныеИзмерения.Тип           = Документы.ТипВсеСсылки();
		ДанныеИзмерения.Представление = НСтр("ru='Регистратор'");
		ДанныеИзмерения.Ведущее       = Истина;
		ОписаниеИзмерений.Вставить("Регистратор", ДанныеИзмерения);

	КонецЕсли;
	
	// Все измерения
	Для Каждого МетаИзмерение Из МетаданныеРегистра.Измерения Цикл
		ДанныеИзмерения = Новый Структура("Ведущее, Представление, Формат, Тип");
		ДанныеИзмерения.Тип           = МетаИзмерение.Тип;
		ДанныеИзмерения.Представление = МетаИзмерение.Представление();
		ДанныеИзмерения.Ведущее       = МетаИзмерение.Ведущее;
		ОписаниеИзмерений.Вставить(МетаИзмерение.Имя, ДанныеИзмерения);
	КонецЦикла;

	КэшИзмеренийРегистров[МетаданныеРегистра] = ОписаниеИзмерений;
	Возврат ОписаниеИзмерений;

КонецФункции

#КонецОбласти

#Область ЗаменитьСсылки

Функция РазметитьМестаИспользования(Знач ПараметрыВыполнения, Знач Ссылка, Знач ЦелеваяСсылка, Знач ТаблицаПоиска)
	УстановитьПривилегированныйРежим(Истина);
	
	// Устанавливаем порядок известных и проверяем наличие неопознанных объектов.
	Результат = Новый Структура;
	Результат.Вставить("МестаИспользования", ТаблицаПоиска.НайтиСтроки(Новый Структура("Ссылка", Ссылка)));
	Результат.Вставить("ОшибкиРазметки", Новый Массив);
	Результат.Вставить("Успех", Истина);

	Для Каждого МестоИспользования Из Результат.МестаИспользования Цикл
		Если МестоИспользования.ЭтоСлужебныеДанные Тогда
			Продолжить; // Зависимые данные не обрабатываются.
		КонецЕсли;

		Информация = ИнформацияОТипе(МестоИспользования.Метаданные, ПараметрыВыполнения);
		Если Информация.Вид = "КОНСТАНТА" Тогда
			МестоИспользования.КлючЗамены = "Константа";
			МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка;

		ИначеЕсли Информация.Вид = "ПОСЛЕДОВАТЕЛЬНОСТЬ" Тогда
			МестоИспользования.КлючЗамены = "Последовательность";
			МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка;

		ИначеЕсли Информация.Вид = "РЕГИСТРСВЕДЕНИЙ" Тогда
			МестоИспользования.КлючЗамены = "РегистрСведений";
			МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка;

		ИначеЕсли Информация.Вид = "РЕГИСТРБУХГАЛТЕРИИ" Или Информация.Вид = "РЕГИСТРНАКОПЛЕНИЯ" Или Информация.Вид
			= "РЕГИСТРРАСЧЕТА" Тогда
			МестоИспользования.КлючЗамены = "КлючЗаписи";
			МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка;

		ИначеЕсли Информация.Ссылочный Тогда
			МестоИспользования.КлючЗамены = "Объект";
			МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка;

		Иначе
			// Неизвестный объект для замены ссылок.
			Результат.Успех = Ложь;
			Текст = СтрШаблон(НСтр("ru = 'Замена ссылок в ""%1"" не поддерживается.'"), Информация.ПолноеИмя);
			ОписаниеОшибки = Новый Структура("Объект, Текст", МестоИспользования.Данные, Текст);
			Результат.ОшибкиРазметки.Добавить(ОписаниеОшибки);
		КонецЕсли;

	КонецЦикла;

	Возврат Результат;
КонецФункции

Процедура ЗаменитьСсылкиКороткимиТранзакциями(Результат, Знач ПараметрыВыполнения, Знач Дубли, Знач ТаблицаПоиска)
	
	// Основной цикл обработки
	ФильтрСсылок = Новый Структура("Ссылка, КлючЗамены");
	Для Каждого Дубль Из Дубли Цикл
		БылиОшибки = Результат.ЕстьОшибки;
		Результат.ЕстьОшибки = Ложь;

		ФильтрСсылок.Ссылка = Дубль;

		ФильтрСсылок.КлючЗамены = "Константа";
		МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок);
		Для Каждого МестоИспользования Из МестаИспользования Цикл
			ПроизвестиЗаменуВКонстанте(Результат, МестоИспользования, ПараметрыВыполнения, Истина);
		КонецЦикла;

		ФильтрСсылок.КлючЗамены = "Объект";
		МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок);
		Для Каждого МестоИспользования Из МестаИспользования Цикл
			ПроизвестиЗаменуВОбъекте(Результат, МестоИспользования, ПараметрыВыполнения, Истина);
		КонецЦикла;

		ФильтрСсылок.КлючЗамены = "КлючЗаписи";
		МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок);
		Для Каждого МестоИспользования Из МестаИспользования Цикл
			ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения, Истина);
		КонецЦикла;

		ФильтрСсылок.КлючЗамены = "Последовательность";
		МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок);
		Для Каждого МестоИспользования Из МестаИспользования Цикл
			ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения, Истина);
		КонецЦикла;

		ФильтрСсылок.КлючЗамены = "РегистрСведений";
		МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок);
		Для Каждого МестоИспользования Из МестаИспользования Цикл
			ПроизвестиЗаменуВРегистреСведений(Результат, МестоИспользования, ПараметрыВыполнения, Истина);
		КонецЦикла;

		Если Не Результат.ЕстьОшибки Тогда
			ПараметрыВыполнения.УспешныеЗамены.Вставить(Дубль, ПараметрыВыполнения.ПарыЗамен[Дубль]);
		КонецЕсли;
		Результат.ЕстьОшибки = Результат.ЕстьОшибки Или БылиОшибки;

	КонецЦикла;
	
	// Окончательные действия
	Если ПараметрыВыполнения.УдалятьНепосредственно Тогда
		УдалитьСсылкиНемонопольно(Результат, Дубли, ПараметрыВыполнения, Истина);

	ИначеЕсли ПараметрыВыполнения.ПомечатьНаУдаление Тогда
		УдалитьСсылкиНемонопольно(Результат, Дубли, ПараметрыВыполнения, Ложь);

	Иначе
		// Поиск новых
		ТаблицаПовторногоПоиска = МестаИспользования(Дубли);
		ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, ТаблицаПовторногоПоиска);
	КонецЕсли;

КонецПроцедуры

Процедура ЗаменитьСсылкуОднойТранзакцией(Результат, Знач Дубль, Знач ПараметрыВыполнения, Знач ТаблицаПоиска)
	УстановитьПривилегированныйРежим(Истина);

	НачатьТранзакцию();
	Попытка
		// 1. Блокирование всех мест использования.
		СостояниеОперации = "ОшибкаБлокировки";
		Блокировка = Новый БлокировкаДанных;

		МестаИспользования = ТаблицаПоиска.НайтиСтроки(Новый Структура("Ссылка", Дубль));
		ЗаблокироватьМестаИспользования(ПараметрыВыполнения, Блокировка, МестаИспользования);
		Блокировка.Заблокировать();
		СостояниеОперации = "";

		УстановитьПривилегированныйРежим(Ложь);
		
		// 2. Замена везде до первой ошибки.
		Результат.ЕстьОшибки = Ложь;

		Для Каждого МестоИспользования Из МестаИспользования Цикл

			Если МестоИспользования.КлючЗамены = "Константа" Тогда
				ПроизвестиЗаменуВКонстанте(Результат, МестоИспользования, ПараметрыВыполнения, Ложь);
			ИначеЕсли МестоИспользования.КлючЗамены = "Объект" Тогда
				ПроизвестиЗаменуВОбъекте(Результат, МестоИспользования, ПараметрыВыполнения, Ложь);
			ИначеЕсли МестоИспользования.КлючЗамены = "Последовательность" Тогда
				ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения, Ложь);
			ИначеЕсли МестоИспользования.КлючЗамены = "КлючЗаписи" Тогда
				ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения, Ложь);
			ИначеЕсли МестоИспользования.КлючЗамены = "РегистрСведений" Тогда
				ПроизвестиЗаменуВРегистреСведений(Результат, МестоИспользования, ПараметрыВыполнения, Ложь);
			КонецЕсли;

			Если Результат.ЕстьОшибки Тогда
				ОтменитьТранзакцию();
				Возврат;
			КонецЕсли;

		КонецЦикла;
		
		// 3. Удаление 
		ПроизводимыеЗамены = Новый Массив;
		ПроизводимыеЗамены.Добавить(Дубль);

		Если ПараметрыВыполнения.УдалятьНепосредственно Тогда
			УдалитьСсылкиНемонопольно(Результат, ПроизводимыеЗамены, ПараметрыВыполнения, Истина);

		ИначеЕсли ПараметрыВыполнения.ПомечатьНаУдаление Тогда
			УдалитьСсылкиНемонопольно(Результат, ПроизводимыеЗамены, ПараметрыВыполнения, Ложь);

		Иначе
			// Поиск новых
			ТаблицаПовторногоПоиска = МестаИспользования(ПроизводимыеЗамены);
			ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, ТаблицаПовторногоПоиска);
		КонецЕсли;

		Если Результат.ЕстьОшибки Тогда
			ОтменитьТранзакцию();
			Возврат;
		КонецЕсли;

		ПараметрыВыполнения.УспешныеЗамены.Вставить(Дубль, ПараметрыВыполнения.ПарыЗамен[Дубль]);
		ЗафиксироватьТранзакцию();

	Исключение
		ОтменитьТранзакцию();
		Если СостояниеОперации = "ОшибкаБлокировки" Тогда
			ПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
			Ошибка = СтрШаблон(НСтр("ru = 'Не удалось заблокировать все места использования %1:'") + Символы.ПС
				+ ПредставлениеОшибки, Дубль);
			ЗарегистрироватьОшибкуЗамены(Результат, Дубль, ОписаниеОшибкиЗамены("ОшибкаБлокировки", Неопределено,
				Неопределено, Ошибка));
		Иначе
			ВызватьИсключение;
		КонецЕсли;
	КонецПопытки;

КонецПроцедуры

Процедура ПроизвестиЗаменуВКонстанте(Результат, Знач МестоИспользования, Знач ПараметрыЗаписи,
	Знач ВнутренняяТранзакция = Истина)

	УстановитьПривилегированныйРежим(Истина);

	Данные = МестоИспользования.Данные;
	Мета   = МестоИспользования.Метаданные;

	ПредставлениеДанных = Строка(Данные);
	
	// Будем производить сразу все замены для этих данных.
	Фильтр = Новый Структура("Данные, КлючЗамены", Данные, "Константа");
	ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр);
	// Помечаем как обработанные
	Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
		Строка.КлючЗамены = "";
	КонецЦикла;

	СостояниеОперации = "";
	Ошибка = "";
	Если ВнутренняяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;

	Попытка
		Если ВнутренняяТранзакция Тогда
			Блокировка = Новый БлокировкаДанных;
			Блокировка.Добавить(Мета.ПолноеИмя());
			Попытка
				Блокировка.Заблокировать();
			Исключение
				Ошибка = СтрШаблон(НСтр("ru = 'Не удалось заблокировать константу %1'"), ПредставлениеДанных);
				СостояниеОперации = "ОшибкаБлокировки";
				ВызватьИсключение;
			КонецПопытки;
		КонецЕсли;

		Менеджер = Константы[Мета.Имя].СоздатьМенеджерЗначения();
		Менеджер.Прочитать();

		ЗаменаПроизведена = Ложь;
		Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
			Если Менеджер.Значение = Строка.Ссылка Тогда
				Менеджер.Значение = Строка.ЦелеваяСсылка;
				ЗаменаПроизведена = Истина;
			КонецЕсли;
		КонецЦикла;

		Если Не ЗаменаПроизведена Тогда
			Если ВнутренняяТранзакция Тогда
				ОтменитьТранзакцию();
			КонецЕсли;
			Возврат;
		КонецЕсли;	
		 
		// Пытаемся сохранить
		Если Не ПараметрыЗаписи.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Ложь);
		КонецЕсли;

		Попытка
			ЗаписатьОбъектПриЗаменеСсылок(Менеджер, ПараметрыЗаписи);
		Исключение
			ОписаниеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
			Ошибка = СтрШаблон(НСтр("ru = 'Не удалось записать %1 по причине: %2'"), ПредставлениеДанных,
				ОписаниеОшибки);
			СостояниеОперации = "ОшибкаЗаписи";
			ВызватьИсключение;
		КонецПопытки;

		Если Не ПараметрыЗаписи.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Истина);
		КонецЕсли;

		Если ВнутренняяТранзакция Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;
	Исключение
		Если ВнутренняяТранзакция Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, Мета, ,
			ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		Если СостояниеОперации = "ОшибкаЗаписи" Тогда
			Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
				ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, ОписаниеОшибкиЗамены("ОшибкаЗаписи", Данные,
					ПредставлениеДанных, Ошибка));
			КонецЦикла;
		Иначе
			ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, ОписаниеОшибкиЗамены(СостояниеОперации, Данные,
				ПредставлениеДанных, Ошибка));
		КонецЕсли;
	КонецПопытки;

КонецПроцедуры

Процедура ПроизвестиЗаменуВОбъекте(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения,
	Знач ВнутренняяТранзакция = Истина)

	УстановитьПривилегированныйРежим(Истина);

	Данные = МестоИспользования.Данные;
	
	// Будем производить сразу все замены для этих данных.
	Фильтр = Новый Структура("Данные, КлючЗамены", Данные, "Объект");
	ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр);

	ПредставлениеДанных = ПредметСтрокой(Данные);
	СостояниеОперации = "";
	ТекстОшибки = "";
	Если ВнутренняяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;

	Попытка

		Если ВнутренняяТранзакция Тогда
			Блокировка = Новый БлокировкаДанных;
			ЗаблокироватьМестоИспользования(ПараметрыВыполнения, Блокировка, МестоИспользования);
			Попытка
				Блокировка.Заблокировать();
			Исключение
				СостояниеОперации = "ОшибкаБлокировки";
				ТекстОшибки = СтрШаблон(
					НСтр("ru = 'Не удалось заблокировать объект ""%1"":
						 |%2'"), ПредставлениеДанных, КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
				ВызватьИсключение;
			КонецПопытки;
		КонецЕсли;

		ОбъектыЗаписи = ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования,
			ОбрабатываемыеСтроки);
		
		// Пытаемся сохранить, сам объект идет последним.
		Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Ложь);
		КонецЕсли;

		Попытка
			Если ПараметрыВыполнения.ПараметрыЗаписи.ЗаписьВРежимеЗагрузки Тогда
				// Первая запись без контроля, чтобы устранить циклические ссылки.
				НовыеПараметрыВыполнения = УИ_ОбщегоНазначенияКлиентСервер.СкопироватьРекурсивно(ПараметрыВыполнения);
				НовыеПараметрыВыполнения.ПараметрыЗаписи.ЗаписьВРежимеЗагрузки  = Ложь;
				Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл
					ЗаписатьОбъектПриЗаменеСсылок(КлючЗначение.Ключ, НовыеПараметрыВыполнения);
				КонецЦикла;
				// Вторая запись c контролем.
				НовыеПараметрыВыполнения.ПараметрыЗаписи.ЗаписьВРежимеЗагрузки  = Истина;
				Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл
					ЗаписатьОбъектПриЗаменеСсылок(КлючЗначение.Ключ, НовыеПараметрыВыполнения);
				КонецЦикла;
			Иначе
				// Запись без контроля бизнес-логики.
				Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл
					ЗаписатьОбъектПриЗаменеСсылок(КлючЗначение.Ключ, ПараметрыВыполнения);
				КонецЦикла;
			КонецЕсли;
		Исключение
			СостояниеОперации = "ОшибкаЗаписи";
			ОписаниеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
			ТекстОшибки = СтрШаблон(НСтр("ru = 'Не удалось записать %1 по причине: %2'"), ПредставлениеДанных,
				ОписаниеОшибки);
			ВызватьИсключение;
		КонецПопытки;

		Если ВнутренняяТранзакция Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;

	Исключение
		Если ВнутренняяТранзакция Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		Информация = ИнформацияОбОшибке();
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка,
			МестоИспользования.Метаданные, , ПодробноеПредставлениеОшибки(Информация));
		Ошибка = ОписаниеОшибкиЗамены(СостояниеОперации, Данные, ПредставлениеДанных, ТекстОшибки);
		Если СостояниеОперации = "ОшибкаЗаписи" Тогда
			Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
				ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, Ошибка);
			КонецЦикла;
		Иначе
			ЗарегистрироватьОшибкуЗамены(Результат, МестоИспользования.Ссылка, Ошибка);
		КонецЕсли;
	КонецПопытки;
	
	// Помечаем как обработанные
	Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
		Строка.КлючЗамены = "";
	КонецЦикла;

КонецПроцедуры

Процедура ПроизвестиЗаменуВНаборе(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения,
	Знач ВнутренняяТранзакция = Истина)
	УстановитьПривилегированныйРежим(Истина);

	Данные = МестоИспользования.Данные;
	Мета   = МестоИспользования.Метаданные;

	ПредставлениеДанных = Строка(Данные);
	
	// Будем производить сразу все замены для этих данных.
	Фильтр = Новый Структура("Данные, КлючЗамены");
	ЗаполнитьЗначенияСвойств(Фильтр, МестоИспользования);
	ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр);

	ОписаниеНабора = ОписаниеКлючаЗаписи(Мета);
	НаборЗаписей = ОписаниеНабора.НаборЗаписей;

	ПарыЗамен = Новый Соответствие;
	Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
		ПарыЗамен.Вставить(Строка.Ссылка, Строка.ЦелеваяСсылка);
	КонецЦикла;
	
	// Помечаем как обработанные
	Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
		Строка.КлючЗамены = "";
	КонецЦикла;

	СостояниеОперации = "";
	Ошибка = "";
	Если ВнутренняяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;

	Попытка

		Если ВнутренняяТранзакция Тогда
			// Блокировка и подготовка набора.
			Блокировка = Новый БлокировкаДанных;
			Для Каждого КлючЗначение Из ОписаниеНабора.СписокИзмерений Цикл
				ТипИзмерения = КлючЗначение.Значение;
				Имя          = КлючЗначение.Ключ;
				Значение     = Данные[Имя];

				Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
					ТекущаяСсылка = Строка.Ссылка;
					Если ТипИзмерения.СодержитТип(ТипЗнч(ТекущаяСсылка)) Тогда
						Блокировка.Добавить(ОписаниеНабора.ПространствоБлокировки).УстановитьЗначение(Имя,
							ТекущаяСсылка);
					КонецЕсли;
				КонецЦикла;

				НаборЗаписей.Отбор[Имя].Установить(Значение);
			КонецЦикла;

			Попытка
				Блокировка.Заблокировать();
			Исключение
				Ошибка = СтрШаблон(НСтр("ru = 'Не удалось заблокировать набор %1'"), ПредставлениеДанных);
				СостояниеОперации = "ОшибкаБлокировки";
				ВызватьИсключение;
			КонецПопытки;

		КонецЕсли;

		НаборЗаписей.Прочитать();
		ЗаменитьВКоллекцииСтрок("НаборЗаписей", "НаборЗаписей", НаборЗаписей, НаборЗаписей, ОписаниеНабора.СписокПолей,
			ПарыЗамен);

		Если НаборЗаписей.Модифицированность() Тогда
			Если ВнутренняяТранзакция Тогда
				ОтменитьТранзакцию();
			КонецЕсли;
			Возврат;
		КонецЕсли;

		Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Ложь);
		КонецЕсли;

		Попытка
			ЗаписатьОбъектПриЗаменеСсылок(НаборЗаписей, ПараметрыВыполнения);
		Исключение
			ОписаниеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
			Ошибка = СтрШаблон(НСтр("ru = 'Не удалось записать %1 по причине: %2'"), ПредставлениеДанных,
				ОписаниеОшибки);
			СостояниеОперации = "ОшибкаЗаписи";
			ВызватьИсключение;
		КонецПопытки;

		Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Истина);
		КонецЕсли;

		Если ВнутренняяТранзакция Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;

	Исключение
		Если ВнутренняяТранзакция Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		Информация = ИнформацияОбОшибке();
		ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, Мета, ,
			ПодробноеПредставлениеОшибки(Информация));
		Ошибка = ОписаниеОшибкиЗамены(СостояниеОперации, Данные, ПредставлениеДанных, Ошибка);
		Если СостояниеОперации = "ОшибкаЗаписи" Тогда
			Для Каждого Строка Из ОбрабатываемыеСтроки Цикл
				ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, Ошибка);
			КонецЦикла;
		Иначе
			ЗарегистрироватьОшибкуЗамены(Результат, МестоИспользования.Ссылка, Ошибка);
		КонецЕсли;
	КонецПопытки;

КонецПроцедуры

Процедура ПроизвестиЗаменуВРегистреСведений(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения,
	Знач ВнутренняяТранзакция = Истина)

	Если МестоИспользования.Обработано Тогда
		Возврат;
	КонецЕсли;
	МестоИспользования.Обработано = Истина;
	
	// В случае, если дубль указан в измерениях набора, тогда используется 2 набора записей:
	//     НаборЗаписейДубля - чтение старых значений (по старым измерениям) и удаление старых значений.
	//     НаборЗаписейОригинала - чтение актуальных значений (по новым измерениям) и запись новых значений.
	//     Данные дублей и оригиналов объединяются по правилам:
	//         Приоритет у данных оригинала.
	//         Если в оригинале нет данных, то берутся данные из дубля.
	//     Набор оригинала записывается, а набор дубля удаляется.
	//
	// В случае, если дубль не указан в измерениях набора, тогда используется 1 набор записей:
	//     НаборЗаписейДубля - чтение старых значений и запись новых значений.
	//
	// Замена ссылок в ресурсах и реквизитах производится в обоих случаях.

	УстановитьПривилегированныйРежим(Истина);

	Дубль    = МестоИспользования.Ссылка;
	Оригинал = МестоИспользования.ЦелеваяСсылка;

	МетаданныеРегистра = МестоИспользования.Метаданные;
	КлючЗаписиРегистра = МестоИспользования.Данные;

	Информация = ИнформацияОТипе(МетаданныеРегистра, ПараметрыВыполнения);

	ТребуетсяДваНабора = Ложь;
	Для Каждого КлючЗначение Из Информация.Измерения Цикл
		ЗначениеИзмеренияДубля = КлючЗаписиРегистра[КлючЗначение.Ключ];
		Если ЗначениеИзмеренияДубля = Дубль Или ПараметрыВыполнения.УспешныеЗамены[ЗначениеИзмеренияДубля] = Дубль Тогда
			ТребуетсяДваНабора = Истина; // Дубль указан в измерениях.
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Менеджер = МенеджерОбъектаПоПолномуИмени(Информация.ПолноеИмя);
	//@skip-warning
	НаборЗаписейДубля = Менеджер.СоздатьНаборЗаписей();

	Если ТребуетсяДваНабора Тогда
		ЗначенияИзмеренийОригинала = Новый Структура;
		//@skip-warning
		НаборЗаписейОригинала = Менеджер.СоздатьНаборЗаписей();
	КонецЕсли;

	Если ВнутренняяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;

	Попытка
		Если ВнутренняяТранзакция Тогда
			Блокировка = Новый БлокировкаДанных;
			БлокировкаДубля = Блокировка.Добавить(Информация.ПолноеИмя);
			Если ТребуетсяДваНабора Тогда
				БлокировкаОригинала = Блокировка.Добавить(Информация.ПолноеИмя);
			КонецЕсли;
		КонецЕсли;

		Для Каждого КлючЗначение Из Информация.Измерения Цикл
			ЗначениеИзмеренияДубля = КлючЗаписиРегистра[КлючЗначение.Ключ];
			
			// Для решения проблемы уникальности
			//   выполняется замена старых значений измерений ключа записи на актуальные.
			//   Соответствие старых и актуальных обеспечивает соответствием УспешныеЗамены.
			//   Данные соответствия актуальны на текущий момент времени,
			//   т.к. пополняются только после успешной обработки очередной пары и фиксации транзакции.
			НовоеЗначениеИзмеренияДубля = ПараметрыВыполнения.УспешныеЗамены[ЗначениеИзмеренияДубля];
			Если НовоеЗначениеИзмеренияДубля <> Неопределено Тогда
				ЗначениеИзмеренияДубля = НовоеЗначениеИзмеренияДубля;
			КонецЕсли;

			НаборЗаписейДубля.Отбор[КлючЗначение.Ключ].Установить(ЗначениеИзмеренияДубля);

			Если ВнутренняяТранзакция Тогда // Замена в конкретной паре и блокировка на конкретную замену.
				БлокировкаДубля.УстановитьЗначение(КлючЗначение.Ключ, ЗначениеИзмеренияДубля);
			КонецЕсли;

			Если ТребуетсяДваНабора Тогда
				Если ЗначениеИзмеренияДубля = Дубль Тогда
					ЗначениеИзмеренияОригинала = Оригинал;
				Иначе
					ЗначениеИзмеренияОригинала = ЗначениеИзмеренияДубля;
				КонецЕсли;

				НаборЗаписейОригинала.Отбор[КлючЗначение.Ключ].Установить(ЗначениеИзмеренияОригинала);
				ЗначенияИзмеренийОригинала.Вставить(КлючЗначение.Ключ, ЗначениеИзмеренияОригинала);

				Если ВнутренняяТранзакция Тогда // Замена в конкретной паре и блокировка на конкретную замену.
					БлокировкаОригинала.УстановитьЗначение(КлючЗначение.Ключ, ЗначениеИзмеренияОригинала);
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
		
		// Установка блокировки.
		Если ВнутренняяТранзакция Тогда
			Попытка
				Блокировка.Заблокировать();
			Исключение
				// Вид ошибки "БлокировкаДляРегистра".
				ВызватьИсключение;
			КонецПопытки;
		КонецЕсли;
		
		// Откуда читаем?
		НаборЗаписейДубля.Прочитать();
		Если НаборЗаписейДубля.Количество() = 0 Тогда // Нечего писать.
			Если ВнутренняяТранзакция Тогда
				ОтменитьТранзакцию(); // Замена не требуется.
			КонецЕсли;
			Возврат;
		КонецЕсли;
		ЗаписьДубля = НаборЗаписейДубля[0];
		
		// Куда пишем?
		Если ТребуетсяДваНабора Тогда
			// Пишем в набор с другими измерениями.
			НаборЗаписейОригинала.Прочитать();
			Если НаборЗаписейОригинала.Количество() = 0 Тогда
				ЗаписьОригинала = НаборЗаписейОригинала.Добавить();
				ЗаполнитьЗначенияСвойств(ЗаписьОригинала, ЗаписьДубля);
				ЗаполнитьЗначенияСвойств(ЗаписьОригинала, ЗначенияИзмеренийОригинала);
			Иначе
				ЗаписьОригинала = НаборЗаписейОригинала[0];
			КонецЕсли;
		Иначе
			// Пишем туда-же, откуда и читаем.
			НаборЗаписейОригинала = НаборЗаписейДубля;
			ЗаписьОригинала = ЗаписьДубля; // Ситуация с нулевым количеством записей в наборе обработана выше.
		КонецЕсли;
		
		// Замена дубля на оригинал в ресурсах и реквизитах.
		Для Каждого КлючЗначение Из Информация.Ресурсы Цикл
			ЗначениеРеквизитаВОригинале = ЗаписьОригинала[КлючЗначение.Ключ];
			Если ЗначениеРеквизитаВОригинале = Дубль Тогда
				ЗаписьОригинала[КлючЗначение.Ключ] = Оригинал;
			КонецЕсли;
		КонецЦикла;
		Для Каждого КлючЗначение Из Информация.Реквизиты Цикл
			ЗначениеРеквизитаВОригинале = ЗаписьОригинала[КлючЗначение.Ключ];
			Если ЗначениеРеквизитаВОригинале = Дубль Тогда
				ЗаписьОригинала[КлючЗначение.Ключ] = Оригинал;
			КонецЕсли;
		КонецЦикла;

		Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
			УстановитьПривилегированныйРежим(Ложь);
		КонецЕсли;
		
		// Удаление данных дубля.
		Если ТребуетсяДваНабора Тогда
			НаборЗаписейДубля.Очистить();
			Попытка
				ЗаписатьОбъектПриЗаменеСсылок(НаборЗаписейДубля, ПараметрыВыполнения);
			Исключение
				// Вид ошибки "УдалитьНаборДубля".
				ВызватьИсключение;
			КонецПопытки;
		КонецЕсли;
		
		// Запись данных оригинала.
		Если НаборЗаписейОригинала.Модифицированность() Тогда
			Попытка
				ЗаписатьОбъектПриЗаменеСсылок(НаборЗаписейОригинала, ПараметрыВыполнения);
			Исключение
				// Вид ошибки "ЗаписатьНаборОригинала".
				ВызватьИсключение;
			КонецПопытки;
		КонецЕсли;

		Если ВнутренняяТранзакция Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;
	Исключение
		Если ВнутренняяТранзакция Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		ЗарегистрироватьОшибкуВТаблицу(Результат, Дубль, Оригинал, КлючЗаписиРегистра, Информация,
			"БлокировкаДляРегистра", ИнформацияОбОшибке());
	КонецПопытки;

КонецПроцедуры

Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки)
	Данные = МестоИспользования.Данные;
	ОписаниеПоследовательностей = ОписаниеПоследовательностей(МестоИспользования.Метаданные);
	ОписаниеДвижений            = ОписаниеДвижений(МестоИспользования.Метаданные);

	УстановитьПривилегированныйРежим(Истина);
	
	// Возвращаем измененные обработанные объекты.
	Измененные = Новый Соответствие;
	
	// Считываем
	Описание = ОписаниеОбъекта(Данные.Метаданные());
	Попытка
		Объект = Данные.ПолучитьОбъект();
	Исключение
		// Был уже обработан с ошибками.
		Объект = Неопределено;
	КонецПопытки;

	Если Объект = Неопределено Тогда
		Возврат Измененные;
	КонецЕсли;

	Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл
		ОписаниеДвижения.НаборЗаписей.Отбор.Регистратор.Установить(Данные);
		ОписаниеДвижения.НаборЗаписей.Прочитать();
	КонецЦикла;

	Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл
		ОписаниеПоследовательности.НаборЗаписей.Отбор.Регистратор.Установить(Данные);
		ОписаниеПоследовательности.НаборЗаписей.Прочитать();
	КонецЦикла;
	
	// Заменяем сразу все варианты.
	ПарыЗамен = Новый Соответствие;
	Для Каждого МестоИспользования Из ОбрабатываемыеСтроки Цикл
		ПарыЗамен.Вставить(МестоИспользования.Ссылка, МестоИспользования.ЦелеваяСсылка);
	КонецЦикла;
	
	// Реквизиты
	Для Каждого КлючЗначение Из Описание.Реквизиты Цикл
		Имя = КлючЗначение.Ключ;
		ЦелеваяСсылка = ПарыЗамен[Объект[Имя]];
		Если ЦелеваяСсылка <> Неопределено Тогда
			ЗарегистрироватьФактЗамены(Объект, Объект[Имя], ЦелеваяСсылка, "Реквизиты", Имя);
			Объект[Имя] = ЦелеваяСсылка;
		КонецЕсли;
	КонецЦикла;
	
	// Стандартные реквизиты
	Для Каждого КлючЗначение Из Описание.СтандартныеРеквизиты Цикл
		Имя = КлючЗначение.Ключ;
		ЦелеваяСсылка = ПарыЗамен[Объект[Имя]];
		Если ЦелеваяСсылка <> Неопределено Тогда
			ЗарегистрироватьФактЗамены(Объект, Объект[Имя], ЦелеваяСсылка, "СтандартныеРеквизиты", Имя);
			Объект[Имя] = ЦелеваяСсылка;
		КонецЕсли;
	КонецЦикла;
		
	// Табличные части
	Для Каждого Элемент Из Описание.ТабличныеЧасти Цикл
		ЗаменитьВКоллекцииСтрок(
			"ТабличныеЧасти", Элемент.Имя, Объект, Объект[Элемент.Имя], Элемент.СписокПолей, ПарыЗамен);
	КонецЦикла;
	
	// Стандартные табличные части.
	Для Каждого Элемент Из Описание.СтандартныеТабличныеЧасти Цикл
		ЗаменитьВКоллекцииСтрок(
			"СтандартныеТабличныеЧасти", Элемент.Имя, Объект, Объект[Элемент.Имя], Элемент.СписокПолей, ПарыЗамен);
	КонецЦикла;
		
	// Движения
	Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл
		ЗаменитьВКоллекцииСтрок(
			"Движения", ОписаниеДвижения.ПространствоБлокировки, ОписаниеДвижения.НаборЗаписей,
			ОписаниеДвижения.НаборЗаписей, ОписаниеДвижения.СписокПолей, ПарыЗамен);
	КонецЦикла;
	
	// Последовательности
	Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл
		ЗаменитьВКоллекцииСтрок(
			"Последовательности", ОписаниеПоследовательности.ПространствоБлокировки,
			ОписаниеПоследовательности.НаборЗаписей, ОписаниеПоследовательности.НаборЗаписей,
			ОписаниеПоследовательности.СписокПолей, ПарыЗамен);
	КонецЦикла;

	Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл
		Если ОписаниеДвижения.НаборЗаписей.Модифицированность() Тогда
			Измененные.Вставить(ОписаниеДвижения.НаборЗаписей, Ложь);
		КонецЕсли;
	КонецЦикла;

	Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл
		Если ОписаниеПоследовательности.НаборЗаписей.Модифицированность() Тогда
			Измененные.Вставить(ОписаниеПоследовательности.НаборЗаписей, Ложь);
		КонецЕсли;
	КонецЦикла;
	
	// Сам объект последний - для возможного перепроведения.
	Если Объект.Модифицированность() Тогда
		Измененные.Вставить(Объект, Описание.МожетБытьПроведен);
	КонецЕсли;

	Возврат Измененные;
КонецФункции

Процедура ЗарегистрироватьФактЗамены(Объект, СсылкаДубля, СсылкаОригинала, ВидРеквизита, ИмяРеквизита,
	Индекс = Неопределено, ИмяКолонки = Неопределено)
	Структура = Новый Структура("ДополнительныеСвойства");
	ЗаполнитьЗначенияСвойств(Структура, Объект);
	Если ТипЗнч(Структура.ДополнительныеСвойства) <> Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	ДопСвойства = Объект.ДополнительныеСвойства;
	ДопСвойства.Вставить("ЗаменаСсылок", Истина);
	ВыполненныеЗамены = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ДопСвойства, "ВыполненныеЗамены");
	Если ВыполненныеЗамены = Неопределено Тогда
		ВыполненныеЗамены = Новый Массив;
		ДопСвойства.Вставить("ВыполненныеЗамены", ВыполненныеЗамены);
	КонецЕсли;
	ОписаниеЗамены = Новый Структура;
	ОписаниеЗамены.Вставить("СсылкаДубля", СсылкаДубля);
	ОписаниеЗамены.Вставить("СсылкаОригинала", СсылкаОригинала);
	ОписаниеЗамены.Вставить("ВидРеквизита", ВидРеквизита);
	ОписаниеЗамены.Вставить("ИмяРеквизита", ИмяРеквизита);
	ОписаниеЗамены.Вставить("Индекс", Индекс);
	ОписаниеЗамены.Вставить("ИмяКолонки", ИмяКолонки);
	ВыполненныеЗамены.Добавить(ОписаниеЗамены);
КонецПроцедуры

Процедура УдалитьСсылкиНемонопольно(Результат, Знач СписокСсылок, Знач ПараметрыВыполнения, Знач УдалятьНепосредственно)

	УстановитьПривилегированныйРежим(Истина);

	Удаляемые = Новый Массив;

	ЛокальнаяТранзакция = Не ТранзакцияАктивна();
	Если ЛокальнаяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;

	Попытка
		Для Каждого Ссылка Из СписокСсылок Цикл
			Информация = ИнформацияОТипе(ТипЗнч(Ссылка), ПараметрыВыполнения);
			Блокировка = Новый БлокировкаДанных;
			Блокировка.Добавить(Информация.ПолноеИмя).УстановитьЗначение("Ссылка", Ссылка);
			Попытка
				Блокировка.Заблокировать();
				Удаляемые.Добавить(Ссылка);
			Исключение
				ЗарегистрироватьОшибкуВТаблицу(Результат, Ссылка, Неопределено, Ссылка, Информация,
					"БлокировкаДляУдаленияДубля", ИнформацияОбОшибке());
			КонецПопытки;
		КонецЦикла;

		ТаблицаПоиска = МестаИспользования(Удаляемые);
		Фильтр = Новый Структура("Ссылка");

		Для Каждого Ссылка Из Удаляемые Цикл
			ПредставлениеСсылки = ПредметСтрокой(Ссылка);

			Фильтр.Ссылка = Ссылка;
			МестаИспользования = ТаблицаПоиска.НайтиСтроки(Фильтр);

			Индекс = МестаИспользования.ВГраница();
			Пока Индекс >= 0 Цикл
				Если МестаИспользования[Индекс].ВспомогательныеДанные Тогда
					МестаИспользования.Удалить(Индекс);
				КонецЕсли;
				Индекс = Индекс - 1;
			КонецЦикла;

			Если МестаИспользования.Количество() > 0 Тогда
				ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, МестаИспользования);
				Продолжить; // Остались места использования, нельзя удалять.
			КонецЕсли;

			Объект = Ссылка.ПолучитьОбъект();
			Если Объект = Неопределено Тогда
				Продолжить; // Уже удален.
			КонецЕсли;

			Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
				УстановитьПривилегированныйРежим(Ложь);
			КонецЕсли;

			Попытка
				Если УдалятьНепосредственно Тогда
					ОбработатьОбъектСПерехватомСообщенийПриЗаменеСсылок(Объект, "НепосредственноеУдаление", Неопределено,
						ПараметрыВыполнения);
				Иначе
					ОбработатьОбъектСПерехватомСообщенийПриЗаменеСсылок(Объект, "УстановитьПометкуУдаления",
						Неопределено, ПараметрыВыполнения);
				КонецЕсли;
			Исключение
				ТекстОшибки = НСтр("ru = 'Ошибка удаления'") + Символы.ПС + СокрЛП(КраткоеПредставлениеОшибки(
					ИнформацияОбОшибке()));
				ОписаниеОшибки = ОписаниеОшибкиЗамены("ОшибкаУдаления", Ссылка, ПредставлениеСсылки, ТекстОшибки);
				ЗарегистрироватьОшибкуЗамены(Результат, Ссылка, ОписаниеОшибки);
			КонецПопытки;

			Если Не ПараметрыВыполнения.ПараметрыЗаписи.ПривилегированныйРежим Тогда
				УстановитьПривилегированныйРежим(Истина);
			КонецЕсли;
		КонецЦикла;

		Если ЛокальнаяТранзакция Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;
	Исключение
		Если ЛокальнаяТранзакция Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
	КонецПопытки;

КонецПроцедуры

Процедура ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, ТаблицаПовторногоПоиска)

	Фильтр = Новый Структура("ТипОшибки, Ссылка, ОбъектОшибки", "");
	Для Каждого Строка Из ТаблицаПовторногоПоиска Цикл
		Тест = Новый Структура("ВспомогательныеДанные", Ложь);
		ЗаполнитьЗначенияСвойств(Тест, Строка);
		Если Тест.ВспомогательныеДанные Тогда
			Продолжить;
		КонецЕсли;

		Данные = Строка.Данные;
		Ссылка = Строка.Ссылка;

		ПредставлениеДанных = Строка(Данные);

		Фильтр.ОбъектОшибки = Данные;
		Фильтр.Ссылка       = Ссылка;
		Если Результат.Ошибки.НайтиСтроки(Фильтр).Количество() > 0 Тогда
			Продолжить; // По данной проблеме уже записана ошибка.
		КонецЕсли;
		ЗарегистрироватьОшибкуЗамены(Результат, Ссылка, ОписаниеОшибкиЗамены("ДанныеИзменены", Данные,
			ПредставлениеДанных, НСтр(
			"ru = 'Заменены не все места использования. Возможно места использования были добавлены или изменены другим пользователем.'")));
	КонецЦикла;

КонецПроцедуры

Процедура ЗаблокироватьМестаИспользования(ПараметрыВыполнения, Блокировка, МестаИспользования)

	Для Каждого МестоИспользования Из МестаИспользования Цикл

		ЗаблокироватьМестоИспользования(ПараметрыВыполнения, Блокировка, МестоИспользования);

	КонецЦикла;

КонецПроцедуры

Процедура ЗаблокироватьМестоИспользования(ПараметрыВыполнения, Блокировка, МестоИспользования)

	Если МестоИспользования.КлючЗамены = "Константа" Тогда

		Блокировка.Добавить(МестоИспользования.Метаданные.ПолноеИмя());

	ИначеЕсли МестоИспользования.КлючЗамены = "Объект" Тогда

		СсылкаОбъекта     = МестоИспользования.Данные;
		МетаданныеОбъекта = МестоИспользования.Метаданные;
		
		// Сам объект.
		Блокировка.Добавить(МетаданныеОбъекта.ПолноеИмя()).УстановитьЗначение("Ссылка", СсылкаОбъекта);
		
		// Движения по регистратору.
		ОписаниеДвижений = ОписаниеДвижений(МетаданныеОбъекта);
		Для Каждого Элемент Из ОписаниеДвижений Цикл
			Блокировка.Добавить(Элемент.ПространствоБлокировки + ".НаборЗаписей").УстановитьЗначение("Регистратор",
				СсылкаОбъекта);
		КонецЦикла;
		
		// Последовательности.
		ОписаниеПоследовательностей = ОписаниеПоследовательностей(МетаданныеОбъекта);
		Для Каждого Элемент Из ОписаниеПоследовательностей Цикл
			Блокировка.Добавить(Элемент.ПространствоБлокировки).УстановитьЗначение("Регистратор", СсылкаОбъекта);
		КонецЦикла;

	ИначеЕсли МестоИспользования.КлючЗамены = "Последовательность" Тогда

		СсылкаОбъекта     = МестоИспользования.Данные;
		МетаданныеОбъекта = МестоИспользования.Метаданные;

		ОписаниеПоследовательностей = ОписаниеПоследовательностей(МетаданныеОбъекта);
		Для Каждого Элемент Из ОписаниеПоследовательностей Цикл
			Блокировка.Добавить(Элемент.ПространствоБлокировки).УстановитьЗначение("Регистратор", СсылкаОбъекта);
		КонецЦикла;

	ИначеЕсли МестоИспользования.КлючЗамены = "КлючЗаписи" Или МестоИспользования.КлючЗамены = "РегистрСведений" Тогда

		Информация = ИнформацияОТипе(МестоИспользования.Метаданные, ПараметрыВыполнения);
		ТипДубля = МестоИспользования.ТипСсылки;
		ТипОригинала = ТипЗнч(МестоИспользования.ЦелеваяСсылка);

		Для Каждого КлючЗначение Из Информация.Измерения Цикл
			ТипИзмерения = КлючЗначение.Значение.Тип;
			Если ТипИзмерения.СодержитТип(ТипДубля) Тогда
				БлокировкаПоИзмерению = Блокировка.Добавить(Информация.ПолноеИмя);
				БлокировкаПоИзмерению.УстановитьЗначение(КлючЗначение.Ключ, МестоИспользования.Ссылка);
			КонецЕсли;
			Если ТипИзмерения.СодержитТип(ТипОригинала) Тогда
				БлокировкаПоИзмерению = Блокировка.Добавить(Информация.ПолноеИмя);
				БлокировкаПоИзмерению.УстановитьЗначение(КлючЗначение.Ключ, МестоИспользования.ЦелеваяСсылка);
			КонецЕсли;
		КонецЦикла;

	КонецЕсли;

КонецПроцедуры

Функция ОписаниеДвижений(Знач Мета)
	// можно закэшировать по Мета

	ОписаниеДвижений = Новый Массив;
	Если Не Метаданные.Документы.Содержит(Мета) Тогда
		Возврат ОписаниеДвижений;
	КонецЕсли;

	Для Каждого Движение Из Мета.Движения Цикл

		Если Метаданные.РегистрыНакопления.Содержит(Движение) Тогда
			НаборЗаписей = РегистрыНакопления[Движение.Имя].СоздатьНаборЗаписей();
			ИсключатьПоля = "Активность, НомерСтроки, Период, Регистратор";

		ИначеЕсли Метаданные.РегистрыСведений.Содержит(Движение) Тогда
			НаборЗаписей = РегистрыСведений[Движение.Имя].СоздатьНаборЗаписей();
			ИсключатьПоля = "Активность, ВидДвижения, НомерСтроки, Период, Регистратор";

		ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(Движение) Тогда
			НаборЗаписей = РегистрыБухгалтерии[Движение.Имя].СоздатьНаборЗаписей();
			ИсключатьПоля = "Активность, ВидДвижения, НомерСтроки, Период, Регистратор";

		ИначеЕсли Метаданные.РегистрыРасчета.Содержит(Движение) Тогда
			НаборЗаписей = РегистрыРасчета[Движение.Имя].СоздатьНаборЗаписей();
			ИсключатьПоля = "Активность, БазовыйПериодКонец, БазовыйПериодНачало, НомерСтроки, ПериодДействия,
							|ПериодДействияКонец, ПериодДействияНачало, ПериодРегистрации, Регистратор, Сторно,
							|ФактическийПериодДействия";
		Иначе
			// Неизвестный тип
			Продолжить;
		КонецЕсли;
		
		// Поля ссылочного типа и измерения - кандидаты.
		Описание = СпискиПолейПоТипу(НаборЗаписей, Движение.Измерения, ИсключатьПоля);
		Если Описание.СписокПолей.Количество() = 0 Тогда
			// Незачем обрабатывать
			Продолжить;
		КонецЕсли;

		Описание.Вставить("НаборЗаписей", НаборЗаписей);
		Описание.Вставить("ПространствоБлокировки", Движение.ПолноеИмя());

		ОписаниеДвижений.Добавить(Описание);
	КонецЦикла;	// Метаданные движений

	Возврат ОписаниеДвижений;
КонецФункции

Функция ОписаниеПоследовательностей(Знач Мета)

	ОписаниеПоследовательностей = Новый Массив;
	Если Не Метаданные.Документы.Содержит(Мета) Тогда
		Возврат ОписаниеПоследовательностей;
	КонецЕсли;

	Для Каждого Последовательность Из Метаданные.Последовательности Цикл
		Если Не Последовательность.Документы.Содержит(Мета) Тогда
			Продолжить;
		КонецЕсли;

		ИмяТаблицы = Последовательность.ПолноеИмя();
		
		// Список полей и измерений
		Описание = СпискиПолейПоТипу(ИмяТаблицы, Последовательность.Измерения, "Регистратор");
		Если Описание.СписокПолей.Количество() > 0 Тогда

			Описание.Вставить("НаборЗаписей", Последовательности[Последовательность.Имя].СоздатьНаборЗаписей());
			Описание.Вставить("ПространствоБлокировки", ИмяТаблицы + ".Записи");
			Описание.Вставить("Измерения", Новый Структура);

			ОписаниеПоследовательностей.Добавить(Описание);
		КонецЕсли;

	КонецЦикла;

	Возврат ОписаниеПоследовательностей;
КонецФункции

Функция ОписаниеОбъекта(Знач Мета)
	// можно закэшировать по Мета

	ТипВсеСсылки = ОписаниеТипаВсеСсылки();

	Кандидаты = Новый Структура("Реквизиты, СтандартныеРеквизиты, ТабличныеЧасти, СтандартныеТабличныеЧасти");
	ЗаполнитьЗначенияСвойств(Кандидаты, Мета);

	ОписаниеОбъекта = Новый Структура;

	ОписаниеОбъекта.Вставить("Реквизиты", Новый Структура);
	Если Кандидаты.Реквизиты <> Неопределено Тогда
		Для Каждого МетаРеквизит Из Кандидаты.Реквизиты Цикл
			Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда
				ОписаниеОбъекта.Реквизиты.Вставить(МетаРеквизит.Имя);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	ОписаниеОбъекта.Вставить("СтандартныеРеквизиты", Новый Структура);
	Если Кандидаты.СтандартныеРеквизиты <> Неопределено Тогда
		Исключаемые = Новый Структура("Ссылка");

		Для Каждого МетаРеквизит Из Кандидаты.СтандартныеРеквизиты Цикл
			Имя = МетаРеквизит.Имя;
			Если Не Исключаемые.Свойство(Имя) И ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда
				ОписаниеОбъекта.Реквизиты.Вставить(МетаРеквизит.Имя);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	ОписаниеОбъекта.Вставить("ТабличныеЧасти", Новый Массив);
	Если Кандидаты.ТабличныеЧасти <> Неопределено Тогда
		Для Каждого МетаТаблица Из Кандидаты.ТабличныеЧасти Цикл

			СписокПолей = Новый Структура;
			Для Каждого МетаРеквизит Из МетаТаблица.Реквизиты Цикл
				Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда
					СписокПолей.Вставить(МетаРеквизит.Имя);
				КонецЕсли;
			КонецЦикла;

			Если СписокПолей.Количество() > 0 Тогда
				ОписаниеОбъекта.ТабличныеЧасти.Добавить(Новый Структура("Имя, СписокПолей", МетаТаблица.Имя,
					СписокПолей));
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	ОписаниеОбъекта.Вставить("СтандартныеТабличныеЧасти", Новый Массив);
	Если Кандидаты.СтандартныеТабличныеЧасти <> Неопределено Тогда
		Для Каждого МетаТаблица Из Кандидаты.СтандартныеТабличныеЧасти Цикл

			СписокПолей = Новый Структура;
			Для Каждого МетаРеквизит Из МетаТаблица.СтандартныеРеквизиты Цикл
				Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда
					СписокПолей.Вставить(МетаРеквизит.Имя);
				КонецЕсли;
			КонецЦикла;

			Если СписокПолей.Количество() > 0 Тогда
				ОписаниеОбъекта.СтандартныеТабличныеЧасти.Добавить(Новый Структура("Имя, СписокПолей", МетаТаблица.Имя,
					СписокПолей));
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	ОписаниеОбъекта.Вставить("МожетБытьПроведен", Метаданные.Документы.Содержит(Мета));
	Возврат ОписаниеОбъекта;
КонецФункции

Функция ОписаниеКлючаЗаписи(Знач Мета)
	// можно закэшировать по Мета

	ИмяТаблицы = Мета.ПолноеИмя();
	
	// Поля ссылочного типа - кандидаты и набор измерений.
	ОписаниеКлюча = СпискиПолейПоТипу(ИмяТаблицы, Мета.Измерения, "Период, Регистратор");

	Если Метаданные.РегистрыСведений.Содержит(Мета) Тогда
		НаборЗаписей = РегистрыСведений[Мета.Имя].СоздатьНаборЗаписей();

	ИначеЕсли Метаданные.РегистрыНакопления.Содержит(Мета) Тогда
		НаборЗаписей = РегистрыНакопления[Мета.Имя].СоздатьНаборЗаписей();

	ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(Мета) Тогда
		НаборЗаписей = РегистрыБухгалтерии[Мета.Имя].СоздатьНаборЗаписей();

	ИначеЕсли Метаданные.РегистрыРасчета.Содержит(Мета) Тогда
		НаборЗаписей = РегистрыРасчета[Мета.Имя].СоздатьНаборЗаписей();

	ИначеЕсли Метаданные.Последовательности.Содержит(Мета) Тогда
		НаборЗаписей = Последовательности[Мета.Имя].СоздатьНаборЗаписей();

	Иначе
		НаборЗаписей = Неопределено;

	КонецЕсли;

	ОписаниеКлюча.Вставить("НаборЗаписей", НаборЗаписей);
	ОписаниеКлюча.Вставить("ПространствоБлокировки", ИмяТаблицы);

	Возврат ОписаниеКлюча;
КонецФункции

Функция ОписанияТиповПересекаются(Знач Описание1, Знач Описание2)

	Для Каждого Тип Из Описание1.Типы() Цикл
		Если Описание2.СодержитТип(Тип) Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;

	Возврат Ложь;
КонецФункции

// Возвращает описание по имени таблицы или по набору записей.
Функция СпискиПолейПоТипу(Знач ИсточникДанных, Знач МетаИзмерения, Знач ИсключатьПоля)
	// можно закэшировать

	Описание = Новый Структура;
	Описание.Вставить("СписокПолей", Новый Структура);
	Описание.Вставить("СтруктураИзмерений", Новый Структура);
	Описание.Вставить("СписокВедущих", Новый Структура);

	ТипКонтроля = ОписаниеТипаВсеСсылки();
	Исключаемые = Новый Структура(ИсключатьПоля);

	ТипИсточникаДанных = ТипЗнч(ИсточникДанных);

	Если ТипИсточникаДанных = Тип("Строка") Тогда
		// Источник - имя таблицы, получаем поля запросом.
		Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ " + ИсточникДанных + " ГДЕ ЛОЖЬ");
		ИсточникПолей = Запрос.Выполнить();
	Иначе
		// Источник - набор записей
		ИсточникПолей = ИсточникДанных.ВыгрузитьКолонки();
	КонецЕсли;

	Для Каждого Колонка Из ИсточникПолей.Колонки Цикл
		Имя = Колонка.Имя;
		Если Не Исключаемые.Свойство(Имя) И ОписанияТиповПересекаются(Колонка.ТипЗначения, ТипКонтроля) Тогда
			Описание.СписокПолей.Вставить(Имя);
			
			// И проверка на ведущее измерение.
			Мета = МетаИзмерения.Найти(Имя);
			Если Мета <> Неопределено Тогда
				Описание.СтруктураИзмерений.Вставить(Имя, Мета.Тип);
				Тест = Новый Структура("Ведущее", Ложь);
				ЗаполнитьЗначенияСвойств(Тест, Мета);
				Если Тест.Ведущее Тогда
					Описание.СписокВедущих.Вставить(Имя, Мета.Тип);
				КонецЕсли;
			КонецЕсли;

		КонецЕсли;

	КонецЦикла;

	Возврат Описание;
КонецФункции

Процедура ЗаменитьВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СписокПолей, Знач ПарыЗамен)
	РабочаяКоллекция = Коллекция.Выгрузить();
	Модифицировано = Ложь;

	Для Каждого Строка Из РабочаяКоллекция Цикл

		Для Каждого КлючЗначение Из СписокПолей Цикл
			Имя = КлючЗначение.Ключ;
			ЦелеваяСсылка = ПарыЗамен[Строка[Имя]];
			Если ЦелеваяСсылка <> Неопределено Тогда
				ЗарегистрироватьФактЗамены(Объект, Строка[Имя], ЦелеваяСсылка, ВидКоллекции, ИмяКоллекции,
					РабочаяКоллекция.Индекс(Строка), Имя);
				Строка[Имя] = ЦелеваяСсылка;
				Модифицировано = Истина;
			КонецЕсли;
		КонецЦикла;

	КонецЦикла;

	Если Модифицировано Тогда
		Коллекция.Загрузить(РабочаяКоллекция);
	КонецЕсли;
КонецПроцедуры

Процедура ОбработатьОбъектСПерехватомСообщенийПриЗаменеСсылок(Знач Объект, Знач Действие, Знач РежимЗаписи,
	Знач ПараметрыЗаписи)
	
	// Текущие сообщения до исключения запоминаем.
	ПредыдущиеСообщения = ПолучитьСообщенияПользователю(Истина);
	СообщатьПовторно    = ТекущийРежимЗапуска() <> Неопределено;

	Если Не ЗаписатьОбъектВБазу(Объект, ПараметрыЗаписи.ПараметрыЗаписи, Действие, РежимЗаписи, Истина) Тогда
		// Перехватываем все сообщенное при ошибке и добавляем их в одно исключение.
		ТекстИсключения = "";
		Для Каждого Сообщение Из ПолучитьСообщенияПользователю(Ложь) Цикл
			ТекстИсключения = ТекстИсключения + Символы.ПС + Сообщение.Текст;
		КонецЦикла;
		
		// Сообщаем предыдущие
		Если СообщатьПовторно Тогда
			СообщитьОтложенныеСообщения(ПредыдущиеСообщения);
		КонецЕсли;

		Если ТекстИсключения = "" Тогда
			ВызватьИсключение "";
		Иначе
			ВызватьИсключение СокрЛП(ТекстИсключения);
		КонецЕсли;
	КонецЕсли;

	Если СообщатьПовторно Тогда
		СообщитьОтложенныеСообщения(ПредыдущиеСообщения);
	КонецЕсли;

КонецПроцедуры

Процедура СообщитьОтложенныеСообщения(Знач Сообщения)

	Для Каждого Сообщение Из Сообщения Цикл
		Сообщение.Сообщить();
	КонецЦикла;

КонецПроцедуры

Процедура ЗаписатьОбъектПриЗаменеСсылок(Знач Объект, Знач ПараметрыЗаписи)

	МетаданныеОбъекта = Объект.Метаданные();

	Если ЭтоДокумент(МетаданныеОбъекта) Тогда
		ОбработатьОбъектСПерехватомСообщенийПриЗаменеСсылок(Объект, "Запись", РежимЗаписиДокумента.Запись,
			ПараметрыЗаписи);
		Возврат;
	КонецЕсли;
	
	// Проверка на возможные циклические ссылки.
	СвойстваОбъекта = Новый Структура("Иерархический, ВидыСубконто, Владельцы", Ложь, Неопределено, Новый Массив);
	ЗаполнитьЗначенияСвойств(СвойстваОбъекта, МетаданныеОбъекта);
	
	// По родителю
	Если СвойстваОбъекта.Иерархический Или СвойстваОбъекта.ВидыСубконто <> Неопределено Тогда

		Если Объект.Родитель = Объект.Ссылка Тогда
			ВызватьИсключение СтрШаблон(
				НСтр("ru = 'При записи ""%1"" возникает циклическая ссылка в иерархии.'"), Строка(Объект));
		КонецЕсли;

	КонецЕсли;
	
	// По владельцу
	Если СвойстваОбъекта.Владельцы.Количество() > 1 И Объект.Владелец = Объект.Ссылка Тогда
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'При записи ""%1"" возникает циклическая ссылка в подчинении.'"), Строка(Объект));
	КонецЕсли;
	
	// Для последовательностей право "Изменение" может отсутствовать даже у роли "АдминистраторСистемы".
	Если ЭтоПоследовательность(МетаданныеОбъекта) И Не ПравоДоступа("Изменение", МетаданныеОбъекта)
		И УИ_Пользователи.ЭтоПолноправныйПользователь( , , Ложь) Тогда

		УстановитьПривилегированныйРежим(Истина);
	КонецЕсли;
	
	// Просто запись
	ОбработатьОбъектСПерехватомСообщенийПриЗаменеСсылок(Объект, "Запись", Неопределено, ПараметрыЗаписи);
КонецПроцедуры

Функция СобытиеЖурналаРегистрацииЗаменыСсылок()

	Возврат НСтр("ru='Поиск и удаление ссылок'", УИ_ОбщегоНазначенияКлиентСервер.КодОсновногоЯзыка());

КонецФункции

Процедура ЗарегистрироватьОшибкуВТаблицу(Результат, Дубль, Оригинал, Данные, Информация, ТипОшибки, ИнформацияОбОшибке)
	Результат.ЕстьОшибки = Истина;

	ЗаписьЖурналаРегистрации(
		СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(
		ИнформацияОбОшибке));

	ПолноеПредставлениеДанных = Строка(Данные) + " (" + Информация.ПредставлениеЭлемента + ")";

	Ошибка = Результат.Ошибки.Добавить();
	Ошибка.Ссылка       = Дубль;
	Ошибка.ОбъектОшибки = Данные;
	Ошибка.ПредставлениеОбъектаОшибки = ПолноеПредставлениеДанных;

	Если ТипОшибки = "БлокировкаДляРегистра" Тогда
		НовыйШаблон = НСтр("ru = 'Не удалось начать редактирование %1: %2'");
		Ошибка.ТипОшибки = "ОшибкаБлокировки";
	ИначеЕсли ТипОшибки = "БлокировкаДляУдаленияДубля" Тогда
		НовыйШаблон = НСтр("ru = 'Не удалось начать удаление: %2'");
		Ошибка.ТипОшибки = "ОшибкаБлокировки";
	ИначеЕсли ТипОшибки = "УдалитьНаборДубля" Тогда
		НовыйШаблон = НСтр("ru = 'Не удалось очистить сведения о дубле в %1: %2'");
		Ошибка.ТипОшибки = "ОшибкаЗаписи";
	ИначеЕсли ТипОшибки = "ЗаписатьНаборОригинала" Тогда
		НовыйШаблон = НСтр("ru = 'Не удалось обновить сведения в %1: %2'");
		Ошибка.ТипОшибки = "ОшибкаЗаписи";
	Иначе
		НовыйШаблон = ТипОшибки + " (%1): %2";
		Ошибка.ТипОшибки = ТипОшибки;
	КонецЕсли;

	НовыйШаблон = НовыйШаблон + Символы.ПС + Символы.ПС + НСтр("ru = 'Подробности в журнале регистрации.'");

	КраткоеПредставление = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
	Ошибка.ТекстОшибки = СтрШаблон(НовыйШаблон, ПолноеПредставлениеДанных, КраткоеПредставление);

КонецПроцедуры

// Формирует информацию о типе объекта метаданных: полное имя, представления, вид и т.п.
Функция ИнформацияОТипе(ПолноеИмяИлиМетаданныеИлиТип, Кэш)
	ТипПервогоПараметра = ТипЗнч(ПолноеИмяИлиМетаданныеИлиТип);
	Если ТипПервогоПараметра = Тип("Строка") Тогда
		ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяИлиМетаданныеИлиТип);
	Иначе
		Если ТипПервогоПараметра = Тип("Тип") Тогда // Поиск объекта метаданных.
			ОбъектМетаданных = Метаданные.НайтиПоТипу(ПолноеИмяИлиМетаданныеИлиТип);
		Иначе
			ОбъектМетаданных = ПолноеИмяИлиМетаданныеИлиТип;
		КонецЕсли;
	КонецЕсли;
	ПолноеИмя = ВРег(ОбъектМетаданных.ПолноеИмя());

	ИнформацияОТипах = УИ_ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Кэш, "ИнформацияОТипах");
	Если ИнформацияОТипах = Неопределено Тогда
		ИнформацияОТипах = Новый Соответствие;
		Кэш.Вставить("ИнформацияОТипах", ИнформацияОТипах);
	Иначе
		Информация = ИнформацияОТипах.Получить(ПолноеИмя);
		Если Информация <> Неопределено Тогда
			Возврат Информация;
		КонецЕсли;
	КонецЕсли;

	Информация = Новый Структура("ПолноеИмя, ПредставлениеЭлемента, ПредставлениеСписка,
								 |Вид, Ссылочный, Технический, Разделенный,
								 |Иерархический,
								 |ЕстьПодчиненные, ИменаПодчиненных,
								 |Измерения, Реквизиты, Ресурсы");
	ИнформацияОТипах.Вставить(ПолноеИмя, Информация);
	
	// Заполнение базовой информации.
	Информация.ПолноеИмя = ПолноеИмя;
	
	// Представления: элемента и списка.
	СтандартныеСвойства = Новый Структура("ПредставлениеОбъекта, РасширенноеПредставлениеОбъекта, ПредставлениеСписка, РасширенноеПредставлениеСписка");
	ЗаполнитьЗначенияСвойств(СтандартныеСвойства, ОбъектМетаданных);
	Если ЗначениеЗаполнено(СтандартныеСвойства.ПредставлениеОбъекта) Тогда
		Информация.ПредставлениеЭлемента = СтандартныеСвойства.ПредставлениеОбъекта;
	ИначеЕсли ЗначениеЗаполнено(СтандартныеСвойства.РасширенноеПредставлениеОбъекта) Тогда
		Информация.ПредставлениеЭлемента = СтандартныеСвойства.РасширенноеПредставлениеОбъекта;
	Иначе
		Информация.ПредставлениеЭлемента = ОбъектМетаданных.Представление();
	КонецЕсли;
	Если ЗначениеЗаполнено(СтандартныеСвойства.ПредставлениеСписка) Тогда
		Информация.ПредставлениеСписка = СтандартныеСвойства.ПредставлениеСписка;
	ИначеЕсли ЗначениеЗаполнено(СтандартныеСвойства.РасширенноеПредставлениеСписка) Тогда
		Информация.ПредставлениеСписка = СтандартныеСвойства.РасширенноеПредставлениеСписка;
	Иначе
		Информация.ПредставлениеСписка = ОбъектМетаданных.Представление();
	КонецЕсли;
	
	// Вид и его свойства.
	Информация.Вид = Лев(Информация.ПолноеИмя, СтрНайти(Информация.ПолноеИмя, ".") - 1);
	Если Информация.Вид = "СПРАВОЧНИК" Или Информация.Вид = "ДОКУМЕНТ" Или Информация.Вид = "ПЕРЕЧИСЛЕНИЕ"
		Или Информация.Вид = "ПЛАНВИДОВХАРАКТЕРИСТИК" Или Информация.Вид = "ПЛАНСЧЕТОВ" Или Информация.Вид = "ПЛАНВИДОВРАСЧЕТА"
		Или Информация.Вид = "БИЗНЕСПРОЦЕСС" Или Информация.Вид = "ЗАДАЧА" Или Информация.Вид = "ПЛАНОБМЕНА" Тогда
		Информация.Ссылочный = Истина;
	Иначе
		Информация.Ссылочный = Ложь;
	КонецЕсли;

	Если Информация.Вид = "СПРАВОЧНИК" Или Информация.Вид = "ПЛАНВИДОВХАРАКТЕРИСТИК" Тогда
		Информация.Иерархический = ОбъектМетаданных.Иерархический;
	ИначеЕсли Информация.Вид = "ПЛАНСЧЕТОВ" Тогда
		Информация.Иерархический = Истина;
	Иначе
		Информация.Иерархический = Ложь;
	КонецЕсли;

	Информация.ЕстьПодчиненные = Ложь;
	Если Информация.Вид = "СПРАВОЧНИК" Или Информация.Вид = "ПЛАНВИДОВХАРАКТЕРИСТИК" Или Информация.Вид = "ПЛАНОБМЕНА"
		Или Информация.Вид = "ПЛАНСЧЕТОВ" Или Информация.Вид = "ПЛАНВИДОВРАСЧЕТА" Тогда
		Для Каждого Справочник Из Метаданные.Справочники Цикл
			Если Справочник.Владельцы.Содержит(ОбъектМетаданных) Тогда
				Если Информация.ЕстьПодчиненные = Ложь Тогда
					Информация.ЕстьПодчиненные = Истина;
					Информация.ИменаПодчиненных = Новый Массив;
				КонецЕсли;
				Информация.ИменаПодчиненных.Добавить(Справочник.ПолноеИмя());
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;

	Если Информация.ПолноеИмя = "СПРАВОЧНИК.ИДЕНТИФИКАТОРЫОБЪЕКТОВМЕТАДАННЫХ" Или Информация.ПолноеИмя
		= "СПРАВОЧНИК.ПРЕДОПРЕДЕЛЕННЫЕВАРИАНТЫОТЧЕТОВ" Тогда
		Информация.Технический = Истина;
		Информация.Разделенный = Ложь;
	Иначе
		Информация.Технический = Ложь;
		Если Не Кэш.Свойство("МодельСервиса") Тогда
			Кэш.Вставить("МодельСервиса", РазделениеВключено());
			Если Кэш.МодельСервиса Тогда
//
//				Если ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
//					МодульРаботаВМоделиСервиса = ОбщийМодуль("РаботаВМоделиСервиса");
//					РазделительОсновныхДанных = МодульРаботаВМоделиСервиса.РазделительОсновныхДанных();
//					РазделительВспомогательныхДанных = МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных();
//				Иначе
					РазделительОсновныхДанных = Неопределено;
					РазделительВспомогательныхДанных = Неопределено;
//				КонецЕсли;

				Кэш.Вставить("ВОбластиДанных", РазделениеВключено() И ДоступноИспользованиеРазделенныхДанных());
				Кэш.Вставить("РазделительОсновныхДанных", РазделительОсновныхДанных);
				Кэш.Вставить("РазделительВспомогательныхДанных", РазделительВспомогательныхДанных);
			КонецЕсли;
		КонецЕсли;
		Если Кэш.МодельСервиса Тогда
//			Если ПодсистемаСуществует("ТехнологияСервиса.БазоваяФункциональность") Тогда
//				МодульРаботаВМоделиСервиса = ОбщийМодуль("РаботаВМоделиСервиса");
//				Попытка
//					ЭтоРазделенныйОбъектМетаданных = МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(
//					ОбъектМетаданных);
//				Исключение
//					ЭтоРазделенныйОбъектМетаданных = Истина;
//				КонецПопытки;
//			Иначе
				ЭтоРазделенныйОбъектМетаданных = Истина;
//			КонецЕсли;
			Информация.Разделенный = ЭтоРазделенныйОбъектМетаданных;
		КонецЕсли;
	КонецЕсли;

	Информация.Измерения = Новый Структура;
	Информация.Реквизиты = Новый Структура;
	Информация.Ресурсы = Новый Структура;

	ВидыРеквизитов = Новый Структура("СтандартныеРеквизиты, Реквизиты, Измерения, Ресурсы");
	ЗаполнитьЗначенияСвойств(ВидыРеквизитов, ОбъектМетаданных);
	Для Каждого КлючИЗначение Из ВидыРеквизитов Цикл
		Коллекция = КлючИЗначение.Значение;
		Если ТипЗнч(Коллекция) = Тип("КоллекцияОбъектовМетаданных") Тогда
			КудаПишем = ?(Информация.Свойство(КлючИЗначение.Ключ), Информация[КлючИЗначение.Ключ], Информация.Реквизиты);
			Для Каждого Реквизит Из Коллекция Цикл
				КудаПишем.Вставить(Реквизит.Имя, ИнформацияПоРеквизиту(Реквизит));
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	Если Информация.Вид = "РЕГИСТРСВЕДЕНИЙ" И ОбъектМетаданных.ПериодичностьРегистраСведений
		<> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
		ИнформацияПоРеквизиту = Новый Структура("Ведущее, Представление, Формат, Тип, ЗначениеПоУмолчанию, ЗаполнятьИзДанныхЗаполнения");
		ИнформацияПоРеквизиту.Ведущее = Ложь;
		ИнформацияПоРеквизиту.ЗаполнятьИзДанныхЗаполнения = Ложь;
		Если ОбъектМетаданных.ПериодичностьРегистраСведений
			= Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.ПозицияРегистратора Тогда
			ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов("МоментВремени");
		ИначеЕсли ОбъектМетаданных.ПериодичностьРегистраСведений
			= Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Секунда Тогда
			ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя));
		Иначе
			ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата));
		КонецЕсли;
		Информация.Измерения.Вставить("Период", ИнформацияПоРеквизиту);
	КонецЕсли;

	Возврат Информация;
КонецФункции

Функция ИнформацияПоРеквизиту(МетаданныеРеквизита)
	// ОписаниеСтандартногоРеквизита
	// ОбъектМетаданных: Измерение
	// ОбъектМетаданных: Ресурс
	// ОбъектМетаданных: Реквизит
	Информация = Новый Структура("Ведущее, Представление, Формат, Тип, ЗначениеПоУмолчанию, ЗаполнятьИзДанныхЗаполнения");
	ЗаполнитьЗначенияСвойств(Информация, МетаданныеРеквизита);
	Информация.Представление = МетаданныеРеквизита.Представление();
	Если Информация.ЗаполнятьИзДанныхЗаполнения = Истина Тогда
		Информация.ЗначениеПоУмолчанию = МетаданныеРеквизита.ЗначениеЗаполнения;
	Иначе
		Информация.ЗначениеПоУмолчанию = МетаданныеРеквизита.Тип.ПривестиЗначение();
	КонецЕсли;
	Возврат Информация;
КонецФункции

Функция ЭтоСлужебныеДанные(МестоИспользования, ИсключенияПоискаСсылок)

	ИсключениеПоиска = ИсключенияПоискаСсылок[МестоИспользования.Метаданные];
	
	// Данные может быть как ссылкой так и ключом записи регистра.

	Если ИсключениеПоиска = Неопределено Тогда
		Возврат (МестоИспользования.Ссылка = МестоИспользования.Данные); // Ссылку саму на себя исключаем.
	ИначеЕсли ИсключениеПоиска = "*" Тогда
		Возврат Истина; // Если указано исключить все - считаем все исключением.
	Иначе
		Для Каждого ПутьКРеквизиту Из ИсключениеПоиска Цикл
			// Если указаны исключения.
			
			// Относительный путь к реквизиту:
			//   "<ИмяРеквизитаИлиТЧ>[.<ИмяРеквизитаТЧ>]".

			Если ЭтоСсылка(ТипЗнч(МестоИспользования.Данные)) Тогда 
				
				// Проверка есть ли по исключаемому пути в указанных данных проверяемая ссылка

				ПолноеИмяОбъектаМетаданных = МестоИспользования.Метаданные.ПолноеИмя();

				ТекстЗапроса =
				"ВЫБРАТЬ
				|	ИСТИНА
				|ИЗ
				|	&ПолноеИмяОбъектаМетаданных КАК Таблица
				|ГДЕ
				|	&ПутьКРеквизиту = &ПроверяемаяСсылка
				|	И Таблица.Ссылка = &Ссылка";

				ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПолноеИмяОбъектаМетаданных", ПолноеИмяОбъектаМетаданных);
				ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПутьКРеквизиту", ПутьКРеквизиту);

				Запрос = Новый Запрос;
				Запрос.Текст = ТекстЗапроса;
				Запрос.УстановитьПараметр("ПроверяемаяСсылка", МестоИспользования.Ссылка);
				Запрос.УстановитьПараметр("Ссылка", МестоИспользования.Данные);

				Результат = Запрос.Выполнить();

				Если Не Результат.Пустой() Тогда
					Возврат Истина;
				КонецЕсли;

			Иначе

				БуферДанных = Новый Структура(ПутьКРеквизиту);
				ЗаполнитьЗначенияСвойств(БуферДанных, МестоИспользования.Данные);
				Если БуферДанных[ПутьКРеквизиту] = МестоИспользования.Ссылка Тогда
					Возврат Истина;
				КонецЕсли;

			КонецЕсли;

		КонецЦикла;
	КонецЕсли;

	Возврат Ложь;

КонецФункции

#КонецОбласти

#Область Метаданные

////////////////////////////////////////////////////////////////////////////////
// Функции определения типов объектов метаданных.

// Ссылочные типы данных

// Определяет принадлежность объекта метаданных к общему типу "Документ".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к документам.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является документом.
//
Функция ЭтоДокумент(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Документы.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Справочник".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является справочником.
//
Функция ЭтоСправочник(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Справочники.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Перечисление".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является перечислением.
//
Функция ЭтоПеречисление(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Перечисления.Содержит(ОбъектМетаданных);

КонецФункции

// Это перечисление по типу.
// 
// Параметры:
//  Тип - Тип
// 
// Возвращаемое значение:
//  Булево -  Это перечисление по типу
Функция ЭтоПеречислениеПоТипу(Тип) Экспорт
	Если Не ЭтоСсылка(Тип) Тогда
		Возврат Ложь;
	КонецЕсли;
	ПустаяСсылка = НовоеЗначениеПоТипу(Тип);
	Если ПустаяСсылка = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	МетаданныеСсылки = ПустаяСсылка.Метаданные();
	Возврат ЭтоПеречисление(МетаданныеСсылки);
КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "План обмена".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является планом обмена.
//
Функция ЭтоПланОбмена(ОбъектМетаданных) Экспорт

	Возврат Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "План видов характеристик".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является планом видов характеристик.
//
Функция ЭтоПланВидовХарактеристик(ОбъектМетаданных) Экспорт

	Возврат Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Бизнес-процесс".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является бизнес-процессом.
//
Функция ЭтоБизнесПроцесс(ОбъектМетаданных) Экспорт

	Возврат Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Задача".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является задачей.
//
Функция ЭтоЗадача(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Задачи.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "План счетов".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является планом счетов.
//
Функция ЭтоПланСчетов(ОбъектМетаданных) Экспорт

	Возврат Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "План видов расчета".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является планом видов расчета.
//
Функция ЭтоПланВидовРасчета(ОбъектМетаданных) Экспорт

	Возврат Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных);

КонецФункции

// Регистры

// Определяет принадлежность объекта метаданных к общему типу "Регистр сведений".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является регистром сведений.
//
Функция ЭтоРегистрСведений(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Регистр накопления".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является регистром накопления.
//
Функция ЭтоРегистрНакопления(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Регистр бухгалтерии".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является регистром бухгалтерии.
//
Функция ЭтоРегистрБухгалтерии(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к общему типу "Регистр расчета".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является регистром расчета.
//
Функция ЭтоРегистрРасчета(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных);

КонецФункции

// Константы

// Определяет принадлежность объекта метаданных к общему типу "Константа".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является константой.
//
Функция ЭтоКонстанта(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Константы.Содержит(ОбъектМетаданных);

КонецФункции

// Журналы документов

// Определяет принадлежность объекта метаданных к общему типу "Журнал документов".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является журналом документов.
//
Функция ЭтоЖурналДокументов(ОбъектМетаданных) Экспорт

	Возврат Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных);

КонецФункции

// Последовательности

// Определяет принадлежность объекта метаданных к общему типу "Последовательности".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является последовательностью.
//
Функция ЭтоПоследовательность(ОбъектМетаданных) Экспорт

	Возврат Метаданные.Последовательности.Содержит(ОбъектМетаданных);

КонецФункции

// РегламентныеЗадания

// Определяет принадлежность объекта метаданных к общему типу "Регламентные задания".
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является регламентным заданием.
//
Функция ЭтоРегламентноеЗадание(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегламентныеЗадания.Содержит(ОбъектМетаданных);

КонецФункции

// Общие

// Определяет принадлежность объекта метаданных к типу регистр.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект является каким-либо регистром.
//
Функция ЭтоРегистр(ОбъектМетаданных) Экспорт

	Возврат Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Или Метаданные.РегистрыНакопления.Содержит(
		ОбъектМетаданных) Или Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных)
		Или Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных);

КонецФункции

// Определяет принадлежность объекта метаданных к ссылочному типу.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу.
// 
// Возвращаемое значение:
//   Булево - Истина, если объект ссылочного типа.
//
Функция ЭтоОбъектСсылочногоТипа(ОбъектМетаданных) Экспорт

	ИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя();
	Позиция = СтрНайти(ИмяОбъектаМетаданных, ".");
	Если Позиция > 0 Тогда
		ИмяБазовогоТипа = Лев(ИмяОбъектаМетаданных, Позиция - 1);
		Возврат ИмяБазовогоТипа = "Справочник" Или ИмяБазовогоТипа = "Документ" Или ИмяБазовогоТипа = "БизнесПроцесс"
			Или ИмяБазовогоТипа = "Задача" Или ИмяБазовогоТипа = "ПланСчетов" Или ИмяБазовогоТипа = "ПланОбмена"
			Или ИмяБазовогоТипа = "ПланВидовХарактеристик" Или ИмяБазовогоТипа = "ПланВидовРасчета";
	Иначе
		Возврат Ложь;
	КонецЕсли;

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции для работы с типами, объектами метаданных и их строковыми представлениями.

// Возвращает имена реквизитов объекта заданного типа.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - ссылка на элемент базы данных, для которого требуется получить результат функции;
//  Тип    - Тип - тип значения реквизита.
// 
// Возвращаемое значение:
//  Строка - строка реквизитов объекта метаданных конфигурации, разделенных символом ",".
//
// Пример:
//  РеквизитыОрганизации = ОбщегоНазначения.ИменаРеквизитовПоТипу(Документ.Ссылка, Тип("СправочникСсылка.Организации"));
//
Функция ИменаРеквизитовПоТипу(Ссылка, Тип) Экспорт

	Результат = "";
	//@skip-warning
	МетаданныеОбъекта = Ссылка.Метаданные();

	Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
		Если Реквизит.Тип.СодержитТип(Тип) Тогда
			Результат = Результат + ?(ПустаяСтрока(Результат), "", ", ") + Реквизит.Имя;
		КонецЕсли;
	КонецЦикла;

	Возврат Результат;
КонецФункции

// Возвращает имя базового типа по переданному значению объекта метаданных.
//
// Параметры:
//  ОбъектМетаданных - ОбъектМетаданных - объект метаданных, по которому необходимо определить базовый тип.
// 
// Возвращаемое значение:
//  Строка - имя базового типа по переданному значению объекта метаданных.
//
// Пример:
//  ИмяБазовогоТипа = ОбщегоНазначения.ИмяБазовогоТипаПоОбъектуМетаданных(Метаданные.Справочники.Номенклатура); = "Справочники".
//
Функция ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных) Экспорт

	Если Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда
		Возврат "Документы";

	ИначеЕсли Метаданные.Справочники.Содержит(ОбъектМетаданных) Тогда
		Возврат "Справочники";

	ИначеЕсли Метаданные.Перечисления.Содержит(ОбъектМетаданных) Тогда
		Возврат "Перечисления";

	ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда
		Возврат "РегистрыСведений";

	ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Тогда
		Возврат "РегистрыНакопления";

	ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда
		Возврат "РегистрыБухгалтерии";

	ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда
		Возврат "РегистрыРасчета";

	ИначеЕсли Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных) Тогда
		Возврат "ПланыОбмена";

	ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных) Тогда
		Возврат "ПланыВидовХарактеристик";

	ИначеЕсли Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных) Тогда
		Возврат "БизнесПроцессы";

	ИначеЕсли Метаданные.Задачи.Содержит(ОбъектМетаданных) Тогда
		Возврат "Задачи";

	ИначеЕсли Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных) Тогда
		Возврат "ПланыСчетов";

	ИначеЕсли Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных) Тогда
		Возврат "ПланыВидовРасчета";

	ИначеЕсли Метаданные.Константы.Содержит(ОбъектМетаданных) Тогда
		Возврат "Константы";

	ИначеЕсли Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных) Тогда
		Возврат "ЖурналыДокументов";

	ИначеЕсли Метаданные.Последовательности.Содержит(ОбъектМетаданных) Тогда
		Возврат "Последовательности";

	ИначеЕсли Метаданные.РегламентныеЗадания.Содержит(ОбъектМетаданных) Тогда
		Возврат "РегламентныеЗадания";

	ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных.Родитель())
		И ОбъектМетаданных.Родитель().Перерасчеты.Найти(ОбъектМетаданных.Имя) = ОбъектМетаданных Тогда
		Возврат "Перерасчеты";

	ИначеЕсли Метаданные.ВнешниеИсточникиДанных.Содержит(ОбъектМетаданных) Тогда
		Возврат "ВнешниеИсточникиДанных";

	Иначе

		Возврат "";

	КонецЕсли;

КонецФункции

// Возвращает менеджер объекта по полному имени объекта метаданных.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
//
// Параметры:
//  ПолноеИмя - Строка - полное имя объекта метаданных. Пример: "Справочник.Организации".
//
// Возвращаемое значение:
//  СправочникМенеджер, ДокументМенеджер, ОбработкаМенеджер, РегистрСведенийМенеджер - менеджер объекта.
// 
// Пример:
//  МенеджерСправочника = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени("Справочник.Организации");
//  ПустаяСсылка = МенеджерСправочника.ПустаяСсылка();
//
Функция МенеджерОбъектаПоПолномуИмени(ПолноеИмя) Экспорт
	Перем КлассОМ, ИмяОМ, Менеджер;

	ЧастиИмени = СтрРазделить(ПолноеИмя, ".");

	Если ЧастиИмени.Количество() >= 2 Тогда
		КлассОМ = ЧастиИмени[0];
		ИмяОМ  = ЧастиИмени[1];
	КонецЕсли;

	Если ВРег(КлассОМ) = "ПЛАНОБМЕНА" Тогда
		Менеджер = ПланыОбмена;

	ИначеЕсли ВРег(КлассОМ) = "СПРАВОЧНИК" Тогда
		Менеджер = Справочники;

	ИначеЕсли ВРег(КлассОМ) = "ДОКУМЕНТ" Тогда
		Менеджер = Документы;

	ИначеЕсли ВРег(КлассОМ) = "ЖУРНАЛДОКУМЕНТОВ" Тогда
		Менеджер = ЖурналыДокументов;

	ИначеЕсли ВРег(КлассОМ) = "ПЕРЕЧИСЛЕНИЕ" Тогда
		Менеджер = Перечисления;

	ИначеЕсли ВРег(КлассОМ) = "ОТЧЕТ" Тогда
		Менеджер = Отчеты;

	ИначеЕсли ВРег(КлассОМ) = "ОБРАБОТКА" Тогда
		Менеджер = Обработки;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВХАРАКТЕРИСТИК" Тогда
		Менеджер = ПланыВидовХарактеристик;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНСЧЕТОВ" Тогда
		Менеджер = ПланыСчетов;

	ИначеЕсли ВРег(КлассОМ) = "ПЛАНВИДОВРАСЧЕТА" Тогда
		Менеджер = ПланыВидовРасчета;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРСВЕДЕНИЙ" Тогда
		Менеджер = РегистрыСведений;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРНАКОПЛЕНИЯ" Тогда
		Менеджер = РегистрыНакопления;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРБУХГАЛТЕРИИ" Тогда
		Менеджер = РегистрыБухгалтерии;

	ИначеЕсли ВРег(КлассОМ) = "РЕГИСТРРАСЧЕТА" Тогда
		Если ЧастиИмени.Количество() = 2 Тогда
			// Регистр расчета
			Менеджер = РегистрыРасчета;
		Иначе
			КлассПодчиненногоОМ = ЧастиИмени[2];
			ИмяПодчиненногоОМ = ЧастиИмени[3];
			Если ВРег(КлассПодчиненногоОМ) = "ПЕРЕРАСЧЕТ" Тогда
				// Перерасчет
				Попытка
					Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты;
					ИмяОм = ИмяПодчиненногоОМ;
				Исключение
					Менеджер = Неопределено;
				КонецПопытки;
			КонецЕсли;
		КонецЕсли;

	ИначеЕсли ВРег(КлассОМ) = "БИЗНЕСПРОЦЕСС" Тогда
		Менеджер = БизнесПроцессы;

	ИначеЕсли ВРег(КлассОМ) = "ЗАДАЧА" Тогда
		Менеджер = Задачи;

	ИначеЕсли ВРег(КлассОМ) = "КОНСТАНТА" Тогда
		Менеджер = Константы;

	ИначеЕсли ВРег(КлассОМ) = "ПОСЛЕДОВАТЕЛЬНОСТЬ" Тогда
		Менеджер = Последовательности;
	КонецЕсли;

	Если Менеджер <> Неопределено Тогда
		Попытка
			Возврат Менеджер[ИмяОМ];
		Исключение
			Менеджер = Неопределено;
		КонецПопытки;
	КонецЕсли;

	ВызватьИсключение СтрШаблон(НСтр("ru = 'Неизвестный тип объекта метаданных ""%1""'"), ПолноеИмя);

КонецФункции

// Возвращает менеджер объекта по ссылке на объект.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
// См. также ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - объект, менеджер которого требуется получить.
//
// Возвращаемое значение:
//  СправочникМенеджер, ДокументМенеджер, ОбработкаМенеджер, РегистрСведенийМенеджер - менеджер объекта.
//
// Пример:
//  МенеджерСправочника = ОбщегоНазначения.МенеджерОбъектаПоСсылке(СсылкаНаОрганизацию);
//  ПустаяСсылка = МенеджерСправочника.ПустаяСсылка();
//
Функция МенеджерОбъектаПоСсылке(Ссылка) Экспорт
	
	//@skip-warning
	ИмяОбъекта = Ссылка.Метаданные().Имя;
	ТипСсылки = ТипЗнч(Ссылка);

	Если Справочники.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Справочники[ИмяОбъекта];

	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Документы[ИмяОбъекта];

	ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат БизнесПроцессы[ИмяОбъекта];

	ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыВидовХарактеристик[ИмяОбъекта];

	ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыСчетов[ИмяОбъекта];

	ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыВидовРасчета[ИмяОбъекта];

	ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Задачи[ИмяОбъекта];

	ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат ПланыОбмена[ИмяОбъекта];

	ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда
		Возврат Перечисления[ИмяОбъекта];
	Иначе
		Возврат Неопределено;
	КонецЕсли;

КонецФункции

// Проверка того, что переданный тип является ссылочным типом данных.
// Для типа "Неопределено" возвращается Ложь.
//
// Параметры:
//  ПроверяемыйТип - Тип - для проверки на ссылочный тип данных.
//
// Возвращаемое значение:
//  Булево - Истина, если это ссылка.
//
Функция ЭтоСсылка(ПроверяемыйТип) Экспорт

	Возврат ПроверяемыйТип <> Тип("Неопределено") И ОписаниеТипаВсеСсылки().СодержитТип(ПроверяемыйТип);

КонецФункции

// Проверяет физическое наличие записи в информационной базе данных о переданном значении ссылки.
//
// Параметры:
//  ПроверяемаяСсылка - ЛюбаяСсылка - значение любой ссылки информационной базы данных.
// 
// Возвращаемое значение:
//  Булево - Истина, если существует.
//
Функция СсылкаСуществует(ПроверяемаяСсылка) Экспорт

	ТекстЗапроса = "
				   |ВЫБРАТЬ ПЕРВЫЕ 1
				   |	1
				   |ИЗ
				   |	[ИмяТаблицы]
				   |ГДЕ
				   |	Ссылка = &Ссылка
				   |";

	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "[ИмяТаблицы]", ИмяТаблицыПоСсылке(ПроверяемаяСсылка));

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Ссылка", ПроверяемаяСсылка);

	УстановитьПривилегированныйРежим(Истина);

	Возврат Не Запрос.Выполнить().Пустой();

КонецФункции

// Возвращает имя вида объектов метаданных по ссылке на объект.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
// См. так же ВидОбъектаПоТипу.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - объект, вид которого требуется получить.
//
// Возвращаемое значение:
//  Строка - имя вида объектов метаданных. Например: "Справочник", "Документ".
// 
Функция ВидОбъектаПоСсылке(Ссылка) Экспорт

	Возврат ВидОбъектаПоТипу(ТипЗнч(Ссылка));

КонецФункции 

// Новое значение по типу.
// 
// Параметры:
//  Тип - Тип
// 
// Возвращаемое значение:
//  Неопределено, Произвольный -  Новое значение по типу
Функция НовоеЗначениеПоТипу(Тип) Экспорт
	Попытка
		Возврат Новый (Тип);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

// Возвращает имя вида объектов метаданных по типу объекта.
// Ограничение: не обрабатываются точки маршрутов бизнес-процессов.
// См. так же ВидОбъектаПоСсылке.
//
// Параметры:
//  ТипОбъекта - Тип - Тип прикладного объекта, определенный в конфигурации.
//
// Возвращаемое значение:
//  Строка - имя вида объектов метаданных. Например: "Справочник", "Документ".
// 
Функция ВидОбъектаПоТипу(ТипОбъекта) Экспорт

	Если Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Справочник";

	ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Документ";

	ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "БизнесПроцесс";

	ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланВидовХарактеристик";

	ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланСчетов";

	ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланВидовРасчета";

	ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Задача";

	ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "ПланОбмена";

	ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда
		Возврат "Перечисление";

	Иначе
		ВызватьИсключение СтрШаблон(НСтр("ru='Неверный тип значения параметра (%1)'"), Строка(ТипОбъекта));

	КонецЕсли;

КонецФункции

// Возвращает полное имя объекта метаданных по переданному значению ссылки.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - объект, для которого необходимо получить имя таблицы ИБ.
// 
// Возвращаемое значение:
//  Строка - полное имя объекта метаданных для указанного объекта. Например: "Справочник.Номенклатура".
//
Функция ИмяТаблицыПоСсылке(Ссылка) Экспорт
	
	//@skip-warning
	Возврат Ссылка.Метаданные().ПолноеИмя();

КонецФункции

// Проверяет, что переданное значение имеет ссылочный тип данных.
//
// Параметры:
//  Значение - Произвольный - проверяемое значение.
//
// Возвращаемое значение:
//  Булево - Истина, если тип значения ссылочный.
//
Функция ЗначениеСсылочногоТипа(Значение) Экспорт

	Возврат ЭтоСсылка(ТипЗнч(Значение));

КонецФункции

// Проверяет, является ли объект группой элементов.
//
// Параметры:
//  Объект - ЛюбаяСсылка, Объект - проверяемый объект.
//
// Возвращаемое значение:
//  Булево - Истина, если является.
//
Функция ОбъектЯвляетсяГруппой(Объект) Экспорт

	Если ЗначениеСсылочногоТипа(Объект) Тогда
		Ссылка = Объект;
	Иначе
		//@skip-warning
		Ссылка = Объект.Ссылка;
	КонецЕсли;
	
	//@skip-warning
	МетаданныеОбъекта = Ссылка.Метаданные();

	Если ЭтоСправочник(МетаданныеОбъекта) Тогда

		Если Не МетаданныеОбъекта.Иерархический Или МетаданныеОбъекта.ВидИерархии
			<> Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда

			Возврат Ложь;
		КонецЕсли;

	ИначеЕсли Не ЭтоПланВидовХарактеристик(МетаданныеОбъекта) Тогда
		Возврат Ложь;

	ИначеЕсли Не МетаданныеОбъекта.Иерархический Тогда
		Возврат Ложь;
	КонецЕсли;

	Если Ссылка <> Объект Тогда
		//@skip-warning
		Возврат Объект.ЭтоГруппа;
	КонецЕсли;

	Возврат ЗначениеРеквизитаОбъекта(Ссылка, "ЭтоГруппа") = Истина;

КонецФункции

// Возвращает строковое представление типа. 
// Для ссылочных типов возвращает в формате "СправочникСсылка.ИмяОбъекта" или "ДокументСсылка.ИмяОбъекта".
// Для остальных типов приводит тип к строке, например "Число".
//
// Параметры:
//  Тип - тип - для которого надо получить представление.
//
// Возвращаемое значение:
//  Строка - представление типа.
//
Функция СтроковоеПредставлениеТипа(Тип) Экспорт

	Представление = "";

	Если ЭтоСсылка(Тип) Тогда

		ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
		ИмяОбъекта = СтрРазделить(ПолноеИмя, ".")[1];

		Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "СправочникСсылка";

		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ДокументСсылка";

		ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "БизнесПроцессСсылка";

		ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовХарактеристикСсылка";

		ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланСчетовСсылка";

		ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовРасчетаСсылка";

		ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ЗадачаСсылка";

		ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланОбменаСсылка";

		ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПеречислениеСсылка";

		КонецЕсли;

		Результат = ?(Представление = "", Представление, Представление + "." + ИмяОбъекта);

	Иначе

		Результат = Строка(Тип);

	КонецЕсли;

	Возврат Результат;

КонецФункции

// Возвращает таблицу значений с описанием требуемых свойств всех реквизитов объекта метаданных.
// Получает значения свойств стандартных реквизитов и пользовательских реквизитов (созданных в режиме конфигуратора).
//
// Параметры:
//  ОбъектМетаданных  - ОбъектМетаданных - объект, для которого необходимо получить значение свойств реквизитов.
//                      Например: Метаданные.Документ.РеализацияТоваровИУслуг
//  Свойства - Строка - свойства реквизитов, перечисленные через запятую, значение которых необходимо получить.
//                      Например: "Имя, Тип, Синоним, Подсказка".
//
// Возвращаемое значение:
//  ТаблицаЗначений - описание требуемых свойств всех реквизитов объекта метаданных.
//
Функция ОписаниеСвойствОбъекта(ОбъектМетаданных, Свойства) Экспорт

	МассивСвойств = СтрРазделить(Свойства, ",");
	
	// Возвращаемое значение функции.
	ТаблицаОписанияСвойствОбъекта = Новый ТаблицаЗначений;
	
	// Добавляем в таблицу поля согласно именам переданных свойств.
	Для Каждого ИмяСвойства Из МассивСвойств Цикл
		ТаблицаОписанияСвойствОбъекта.Колонки.Добавить(СокрЛП(ИмяСвойства));
	КонецЦикла;
	
	// Заполняем строку таблицы свойствами реквизитов объекта метаданных.
	Для Каждого Реквизит Из ОбъектМетаданных.Реквизиты Цикл
		ЗаполнитьЗначенияСвойств(ТаблицаОписанияСвойствОбъекта.Добавить(), Реквизит);
	КонецЦикла;
	
	// Заполняем строку таблицы свойствами стандартных реквизитов объекта метаданных.
	Для Каждого Реквизит Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
		ЗаполнитьЗначенияСвойств(ТаблицаОписанияСвойствОбъекта.Добавить(), Реквизит);
	КонецЦикла;

	Возврат ТаблицаОписанияСвойствОбъекта;

КонецФункции

// Возвращает признак того, что реквизит входит в подмножество стандартных реквизитов.
//
// Параметры:
//  СтандартныеРеквизиты - ОписанияСтандартныхРеквизитов - тип и значение, описывающие коллекцию настроек различных
//                                                         стандартных реквизитов;
//  ИмяРеквизита         - Строка - реквизит, который необходимо проверить на принадлежность множеству стандартных
//                                  реквизитов.
// 
// Возвращаемое значение:
//   Булево - Истина, если реквизит входит в подмножество стандартных реквизитов.
//
Функция ЭтоСтандартныйРеквизит(СтандартныеРеквизиты, ИмяРеквизита) Экспорт

	Для Каждого Реквизит Из СтандартныеРеквизиты Цикл
		Если Реквизит.Имя = ИмяРеквизита Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	Возврат Ложь;

КонецФункции

// Позволяет определить, есть ли среди реквизитов объекта реквизит с переданным именем.
//
// Параметры:
//  ИмяРеквизита - Строка - имя реквизита;
//  МетаданныеОбъекта - ОбъектМетаданных - объект, в котором требуется проверить наличие реквизита.
//
// Возвращаемое значение:
//  Булево - Истина, если есть.
//
Функция ЕстьРеквизитОбъекта(ИмяРеквизита, МетаданныеОбъекта) Экспорт

	Возврат Не (МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита) = Неопределено);

КонецФункции

// Проверить, что описание типа состоит из единственного типа значения и 
// совпадает с нужным типом.
//
// Параметры:
//   ОписаниеТипа - ОписаниеТипов - проверяемая коллекция типов;
//   ТипЗначения  - Тип - проверяемый тип.
//
// Возвращаемое значение:
//   Булево - Истина, если совпадает.
//
// Пример:
//  Если ОбщегоНазначения.ОписаниеТипаСостоитИзТипа(ТипЗначенияСвойства, Тип("Булево") Тогда
//    // Выводим поле в виде флажка.
//  КонецЕсли;
//
Функция ОписаниеТипаСостоитИзТипа(ОписаниеТипа, ТипЗначения) Экспорт

	Если ОписаниеТипа.Типы().Количество() = 1 И ОписаниеТипа.Типы().Получить(0) = ТипЗначения Тогда
		Возврат Истина;
	КонецЕсли;

	Возврат Ложь;

КонецФункции

// Возвращает дату создания ссылки.
//
// Параметры:
//  Ссылка - ЛюбаяСсылка - ссылка на элемент базы данных, для которого требуется получить результат функции
// 
// Возвращаемое значение:
//  Дата - дата создания ссылки.
//
Функция ДатаСозданияСсылки(Ссылка) Экспорт
	
	ГУИД = Ссылка.УникальныйИдентификатор();
	Строка16 = Сред(ГУИД, 16, 3) + Сред(ГУИД, 10, 4) + Сред(ГУИД, 1, 8);
	Разрядность = СтрДлина(Строка16);
	ЧислоСек = 0;
	Для Позиция = 1 По Разрядность Цикл
		ЧислоСек = ЧислоСек + СтрНайти("123456789abcdef", Сред(Строка16, Позиция, 1)) * Pow(16, Разрядность - Позиция);
	КонецЦикла;
	ЧислоСек = ЧислоСек / 10000000;
	
	Возврат Дата(1582, 10, 15, 00, 00, 00) + ЧислоСек + СмещениеСтандартногоВремени() + СмещениеЛетнегоВремени();
		
КонецФункции

#КонецОбласти

#Область ХранилищеНастроек

////////////////////////////////////////////////////////////////////////////////
// Сохранение, чтение и удаление настроек из хранилищ.

// Сохраняет настройку в хранилище общих настроек, как метод платформы Сохранить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта       - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек      - Строка           - см. синтакс-помощник платформы.
//   Настройки         - Произвольный     - см. синтакс-помощник платформы.
//   ОписаниеНастроек  - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя   - Строка           - см. синтакс-помощник платформы.
//   ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы.
//
Процедура ХранилищеОбщихНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено,
	ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт
	ХранилищеСохранить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя,
		ОбновитьПовторноИспользуемыеЗначения);

КонецПроцедуры

// Сохраняет несколько настроек в хранилище общих настроек, как метод платформы Сохранить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки.
// 
// Параметры:
//   НесколькоНастроек - Массив - со значениями:
//     * Значение - Структура - со свойствами:
//         * Объект    - Строка       - см. параметр КлючОбъекта  в синтакс-помощнике платформы.
//         * Настройка - Строка       - см. параметр КлючНастроек в синтакс-помощнике платформы.
//         * Значение  - Произвольный - см. параметр Настройки    в синтакс-помощнике платформы.
//
//   ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы.
//
Процедура ХранилищеОбщихНастроекСохранитьМассив(НесколькоНастроек, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт
	УстановитьПривилегированныйРежим(Истина);

	Если Не ПравоДоступа("СохранениеДанныхПользователя", Метаданные) Тогда
		Возврат;
	КонецЕсли;

	Для Каждого Элемент Из НесколькоНастроек Цикл
		ХранилищеОбщихНастроек.Сохранить(Элемент.Объект, КлючНастроек(Элемент.Настройка), Элемент.Значение);
	КонецЦикла;

	Если ОбновитьПовторноИспользуемыеЗначения Тогда
		ОбновитьПовторноИспользуемыеЗначения();
	КонецЕсли;
	УстановитьПривилегированныйРежим(Ложь);

КонецПроцедуры

// Загружает настройку из хранилища общих настроек, как метод платформы Загрузить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Кроме того, возвращает указанное значение по умолчанию, если настройки не найдены.
// Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки.
//
// В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно
// - возвращаемая ссылка заменяется на указанное значение по умолчанию;
// - из данных типа Массив ссылки удаляются;
// - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено;
// - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно.
//
// Параметры:
//   КлючОбъекта          - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек         - Строка           - см. синтакс-помощник платформы.
//   ЗначениеПоУмолчанию  - Произвольный     - значение, которое возвращается, если настройки не найдены.
//                                             Если не указано, возвращается значение Неопределено.
//   ОписаниеНастроек     - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя      - Строка           - см. синтакс-помощник платформы.
//
// Возвращаемое значение: 
//   Произвольный - см. синтакс-помощник платформы.
//
Функция ХранилищеОбщихНастроекЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено,
	ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт

	Возврат ХранилищеЗагрузить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек,
		ИмяПользователя);

КонецФункции

// Удаляет настройку из хранилища общих настроек, как метод платформы Удалить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта     - Строка, Неопределено - см. синтакс-помощник платформы.
//   КлючНастроек    - Строка, Неопределено - см. синтакс-помощник платформы.
//   ИмяПользователя - Строка, Неопределено - см. синтакс-помощник платформы.
//
Процедура ХранилищеОбщихНастроекУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт

	ХранилищеУдалить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, ИмяПользователя);

КонецПроцедуры

// Сохраняет настройку в хранилище системных настроек, как метод платформы Сохранить
// объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек
// более 128 символов путем хеширования части, которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта       - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек      - Строка           - см. синтакс-помощник платформы.
//   Настройки         - Произвольный     - см. синтакс-помощник платформы.
//   ОписаниеНастроек  - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя   - Строка           - см. синтакс-помощник платформы.
//   ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы.
//
Процедура ХранилищеСистемныхНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено,
	ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт

	ХранилищеСохранить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек,
		ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения);

КонецПроцедуры

// Загружает настройку из хранилища системных настроек, как метод платформы Загрузить,
// объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек
// более 128 символов путем хеширования части, которая превышает 96 символов.
// Кроме того, возвращает указанное значение по умолчанию, если настройки не найдены.
// Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки.
//
// В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно:
// - возвращаемая ссылка заменяется на указанное значение по умолчанию;
// - из данных типа Массив ссылки удаляются;
// - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено;
// - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно.
//
// Параметры:
//   КлючОбъекта          - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек         - Строка           - см. синтакс-помощник платформы.
//   ЗначениеПоУмолчанию  - Произвольный     - значение, которое возвращается, если настройки не найдены.
//                                             Если не указано, возвращается значение Неопределено.
//   ОписаниеНастроек     - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя      - Строка           - см. синтакс-помощник платформы.
//
// Возвращаемое значение: 
//   Произвольный - см. синтакс-помощник платформы.
//
Функция ХранилищеСистемныхНастроекЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено,
	ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт

	Возврат ХранилищеЗагрузить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию,
		ОписаниеНастроек, ИмяПользователя);

КонецФункции

// Удаляет настройку из хранилища системных настроек, как метод платформы Удалить,
// объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек
// более 128 символов путем хеширования части, которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта     - Строка, Неопределено - см. синтакс-помощник платформы.
//   КлючНастроек    - Строка, Неопределено - см. синтакс-помощник платформы.
//   ИмяПользователя - Строка, Неопределено - см. синтакс-помощник платформы.
//
Процедура ХранилищеСистемныхНастроекУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт

	ХранилищеУдалить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, ИмяПользователя);

КонецПроцедуры

// Сохраняет настройку в хранилище настроек данных форм, как метод платформы Сохранить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта       - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек      - Строка           - см. синтакс-помощник платформы.
//   Настройки         - Произвольный     - см. синтакс-помощник платформы.
//   ОписаниеНастроек  - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя   - Строка           - см. синтакс-помощник платформы.
//   ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы.
//
Процедура ХранилищеНастроекДанныхФормСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено,
	ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт

	ХранилищеСохранить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек,
		ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения);

КонецПроцедуры

// Загружает настройку из хранилища настроек данных форм, как метод платформы Загрузить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Кроме того, возвращает указанное значение по умолчанию, если настройки не найдены.
// Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки.
//
// В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно
// - возвращаемая ссылка заменяется на указанное значение по умолчанию;
// - из данных типа Массив ссылки удаляются;
// - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено;
// - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно.
//
// Параметры:
//   КлючОбъекта          - Строка           - см. синтакс-помощник платформы.
//   КлючНастроек         - Строка           - см. синтакс-помощник платформы.
//   ЗначениеПоУмолчанию  - Произвольный     - значение, которое возвращается, если настройки не найдены.
//                                             Если не указано, возвращается значение Неопределено.
//   ОписаниеНастроек     - ОписаниеНастроек - см. синтакс-помощник платформы.
//   ИмяПользователя      - Строка           - см. синтакс-помощник платформы.
//
// Возвращаемое значение: 
//   Произвольный - см. синтакс-помощник платформы.
//
Функция ХранилищеНастроекДанныхФормЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено,
	ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт

	Возврат ХранилищеЗагрузить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию,
		ОписаниеНастроек, ИмяПользователя);

КонецФункции

// Удаляет настройку из хранилища настроек данных форм, как метод платформы Удалить,
// объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>,
// но с поддержкой длины ключа настроек более 128 символов путем хеширования части,
// которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки.
//
// Параметры:
//   КлючОбъекта     - Строка, Неопределено - см. синтакс-помощник платформы.
//   КлючНастроек    - Строка, Неопределено - см. синтакс-помощник платформы.
//   ИмяПользователя - Строка, Неопределено - см. синтакс-помощник платформы.
//
Процедура ХранилищеНастроекДанныхФормУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт

	ХранилищеУдалить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, ИмяПользователя);

КонецПроцедуры

// Сохраняет в фоне настройку в хранилище системных настроек, как метод платформы Сохранить
// объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек
// более 128 символов путем хеширования части, которая превышает 96 символов.
// Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки.
//
// Параметры:
//   ПараметрыПроцедуры - Структура -
//  					* КлючОбъекта       - Строка           - см. синтакс-помощник платформы.
//  					* КлючНастроек      - Строка           - см. синтакс-помощник платформы.
//  					* Настройки         - Произвольный     - см. синтакс-помощник платформы.
//  					* ОписаниеНастроек  - ОписаниеНастроек - см. синтакс-помощник платформы.
//  					* ИмяПользователя   - Строка           - см. синтакс-помощник платформы.
//  					* ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы.
//   АдресРезультата - Строка - адрес временного хранилища, в которое нужно
//						поместить результат работы процедуры. Обязательно;
//   АдресДополнительногоРезультата - Строка - если в ПараметрыВыполнения установлен 
//						параметр ДополнительныйРезультат, то содержит адрес дополнительного временного
//						хранилища, в которое нужно поместить результат работы процедуры. Опционально.
//
Процедура ХранилищеСистемныхНастроекСохранитьВФоне(ПараметрыПроцедуры, АдресРезультата, 
												АдресДополнительногоРезультата = Неопределено) Экспорт
	
	Перем КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя;
	ОбновитьПовторноИспользуемыеЗначения = Ложь;
	
	ПараметрыПроцедуры.Свойство("КлючОбъекта", КлючОбъекта);
	ПараметрыПроцедуры.Свойство("КлючНастроек", КлючНастроек);
	ПараметрыПроцедуры.Свойство("Настройки", Настройки);
	ПараметрыПроцедуры.Свойство("ОписаниеНастроек", ОписаниеНастроек);
	ПараметрыПроцедуры.Свойство("ИмяПользователя", ИмяПользователя);
	ПараметрыПроцедуры.Свойство("ОбновитьПовторноИспользуемыеЗначения", ОбновитьПовторноИспользуемыеЗначения);
	
	ХранилищеСистемныхНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек,
									ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения);
	
КонецПроцедуры

#КонецОбласти

#Область Алгоритмы

Функция ВыполнитьАлгоритм(АлгоритмСсылка, ВходящиеПараметры = Неопределено, ОшибкаВыполнения = Ложь,
	СообщениеОбОшибке = "") Экспорт
	Возврат УИ_АлгоритмыКлиентСервер.ВыполнитьАлгоритм(АлгоритмСсылка, ВходящиеПараметры, ОшибкаВыполнения,
		СообщениеОбОшибке)
КонецФункции

Функция ПолучитьСсылкуСправочникАлгоритмы(Алгоритм) Экспорт
	Если ТипЗнч(Алгоритм) = Тип("СправочникСсылка.УИ_Алгоритмы") Тогда
		Возврат Алгоритм;
	ИначеЕсли ТипЗнч(Алгоритм) = Тип("УникальныйИдентификатор") Тогда
		Возврат Справочники.УИ_Алгоритмы.ПолучитьСсылку(Алгоритм);
	ИначеЕсли ТипЗнч(Алгоритм) = Тип("Строка") Тогда
		Если Лев(Алгоритм, 5) = "GUID_" Тогда // БСП внеш. обработка
			СтрокаУИД = Сред(Алгоритм, 6);
			ref = Справочники.УИ_Алгоритмы.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаУИД));
			Возврат ?(ПустаяСтрока(ref.Наименование), Неопределено, ref);
		КонецЕсли;
		НайденПоНаименованию = Справочники.УИ_Алгоритмы.НайтиПоНаименованию(Алгоритм, Истина);
		Если НайденПоНаименованию = Неопределено Тогда
			Попытка
				ЧислоКод = Число(Прав(Алгоритм, 5));
				НайденПоКоду = Справочники.УИ_Алгоритмы.НайтиПоКоду(ЧислоКод);
				Если НайденПоКоду = Неопределено Тогда
					Возврат Неопределено;
				Иначе
					Возврат НайденПоКоду;
				КонецЕсли;
			Исключение
				Возврат Неопределено;
			КонецПопытки;
		Иначе
			Возврат НайденПоНаименованию;
		КонецЕсли;
	Иначе
		Возврат Неопределено;
	КонецЕсли;
КонецФункции

#КонецОбласти

#Область ЗаписьОбъектов

Процедура УстановитьПризнакЗаписиБезАвторегистрацииИзменений(Объект, БезАвторегистрации = Ложь)
	Если Не БезАвторегистрации Тогда
		Возврат;
	КонецЕсли;

	Попытка
		Объект.ОбменДанными.Получатели.Автозаполнение= Не БезАвторегистрации;
	Исключение
				// Элемент плана обмена в 8.3.5+
	КонецПопытки;
КонецПроцедуры

Функция ВыполнитьПроцедуруПередЗаписьюОбъекта(Объект, _ТекстПроцедурыПередЗаписью)
	Результат=Истина;

	Если Не ЗначениеЗаполнено(_ТекстПроцедурыПередЗаписью) Тогда
		Возврат Результат;
	КонецЕсли;

	Попытка
		Выполнить (_ТекстПроцедурыПередЗаписью);
	Исключение
		УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СтрШаблон("Объект: %1. Ошибка при выполнении процедуры ПередЗаписью:
																	   |%2", Объект, КраткоеПредставлениеОшибки(
			ИнформацияОбОшибке())));
		Результат=Ложь;
		;
	КонецПопытки;

	Возврат Результат;
КонецФункции

Функция ЗаписатьОбъектВБазу(Объект, ПараметрыЗаписи, Знач Действие = "Запись", Знач РежимЗаписи = Неопределено,
	ЗаменаСсылок = Ложь) Экспорт

	Если ПараметрыЗаписи.ПривилегированныйРежим Тогда
		УстановитьПривилегированныйРежим(Истина);
	КонецЕсли;

	Если ПараметрыЗаписи.ЗаписьВРежимеЗагрузки Тогда
		Объект.ОбменДанными.Загрузка = Истина;
	КонецЕсли;

	УстановитьПризнакЗаписиБезАвторегистрацииИзменений(Объект, ПараметрыЗаписи.БезАвторегистрацииИзменений);

	Если ПараметрыЗаписи.ИспользоватьДопСвойства И ПараметрыЗаписи.ДополнительныеСвойства.Количество() > 0 Тогда
		Для Каждого КлючЗначение Из ПараметрыЗаписи.ДополнительныеСвойства Цикл
			Объект.ДополнительныеСвойства.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение);
		КонецЦикла;
	КонецЕсли;

	Если ПараметрыЗаписи.ИспользоватьПроцедуруПередЗаписью Тогда
		Если Не ВыполнитьПроцедуруПередЗаписьюОбъекта(Объект, ПараметрыЗаписи.ПроцедураПередЗаписью) Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЕсли;

	Результат=Истина;
	Попытка
		Если Действие = "Запись" Тогда

			Если РежимЗаписи <> Неопределено Тогда
				Объект.Записать(РежимЗаписи);
			Иначе
				Объект.Записать();
			КонецЕсли;

		ИначеЕсли Действие = "УстановитьПометкуУдаления" Тогда
			МетаданныеОбъекта = Объект.Метаданные();

			ЕстьПодчиненные = ЭтоСправочник(МетаданныеОбъекта) 
				ИЛИ ЭтоПланВидовХарактеристик(МетаданныеОбъекта) 
				ИЛИ ЭтоПланСчетов(МетаданныеОбъекта);
				
			Если ЕстьПодчиненные Тогда
				Объект.УстановитьПометкуУдаления(Истина, ЗаменаСсылок);
			Иначе
				Объект.УстановитьПометкуУдаления(Истина);
			КонецЕсли;

		ИначеЕсли Действие = "СнятьПометкуУдаления" Тогда
			Объект.УстановитьПометкуУдаления(Ложь);
		ИначеЕсли Действие = "НепосредственноеУдаление" Тогда

			Объект.Удалить();

		КонецЕсли;

	Исключение
		УИ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		Результат=Ложь;
	КонецПопытки;

	Если ПараметрыЗаписи.ПривилегированныйРежим Тогда
		УстановитьПривилегированныйРежим(Ложь);
	КонецЕсли;

	Возврат Результат;
КонецФункции
#КонецОбласти

#Область УстаревшиеПроцедурыИФункции

// Устарела. Следует использовать УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаСтрока
// Создает объект ОписаниеТипов, содержащий тип Строка.
//
// Параметры:
//  ДлинаСтроки - Число - длина строки.
//
// Возвращаемое значение:
//  ОписаниеТипов - описание типа Строка.
//
Функция ОписаниеТипаСтрока(ДлинаСтроки) Экспорт

	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаСтрока(ДлинаСтроки);

КонецФункции

// Устарела. Следует использовать УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаЧисло
// Создает объект ОписаниеТипов, содержащий тип Число.
//
// Параметры:
//  Разрядность - Число - общее количество разрядов числа (количество разрядов
//                        целой части плюс количество разрядов дробной части).
//  РазрядностьДробнойЧасти - Число - число разрядов дробной части.
//  ЗнакЧисла - ДопустимыйЗнак - допустимый знак числа.
//
// Возвращаемое значение:
//  ОписаниеТипов - описание типа Число.
Функция ОписаниеТипаЧисло(Разрядность, РазрядностьДробнойЧасти = 0, ЗнакЧисла = Неопределено) Экспорт

	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаЧисло(Разрядность, РазрядностьДробнойЧасти, ЗнакЧисла);

КонецФункции

// Устарела. Следует использовать УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаДата
// Создает объект ОписаниеТипов, содержащий тип Дата.
//
// Параметры:
//  ЧастиДаты - ЧастиДаты - набор вариантов использования значений типа Дата.
//
// Возвращаемое значение:
//  ОписаниеТипов - описание типа Дата.
Функция ОписаниеТипаДата(ЧастиДаты) Экспорт
	Возврат УИ_ОбщегоНазначенияКлиентСервер.ОписаниеТипаДата(ЧастиДаты);
КонецФункции


#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Функция КоллекцияВТЗ(Коллекция) Экспорт
	ТЗ = Новый ТаблицаЗначений;
	ТЗ.Колонки.Добавить("Значение");
	Если Не ТипЗнч(Коллекция) = Тип("Массив") Тогда
		ТЗ.Колонки.Добавить("Ключ");
		Для Каждого ТекЭлем Из Коллекция Цикл
			НС=ТЗ.Добавить();
			ЗаполнитьЗначенияСвойств(НС, ТекЭлем);
		КонецЦикла;
	Иначе
		Для I = 0 По Коллекция.ВГраница() Цикл
			ТЗ.Добавить();
		КонецЦикла;
		ТЗ.ЗагрузитьКолонку(Коллекция, 0);
	КонецЕсли;
	Возврат ТЗ;
КонецФункции

// Возвращает серверный модуль менеджера по имени объекта.
Функция СерверныйМодульМенеджера(Имя) 
	ОбъектНайден = Ложь;

	ЧастиИмени = СтрРазделить(Имя, ".");
	Если ЧастиИмени.Количество() = 2 Тогда

		ИмяВида = ВРег(ЧастиИмени[0]);
		ИмяОбъекта = ЧастиИмени[1];

		Если ИмяВида = ВРег("Константы") Тогда
			Если Метаданные.Константы.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("РегистрыСведений") Тогда
			Если Метаданные.РегистрыСведений.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("РегистрыНакопления") Тогда
			Если Метаданные.РегистрыНакопления.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("РегистрыБухгалтерии") Тогда
			Если Метаданные.РегистрыБухгалтерии.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("РегистрыРасчета") Тогда
			Если Метаданные.РегистрыРасчета.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("Справочники") Тогда
			Если Метаданные.Справочники.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("Документы") Тогда
			Если Метаданные.Документы.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("Отчеты") Тогда
			Если Метаданные.Отчеты.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("Обработки") Тогда
			Если Метаданные.Обработки.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("БизнесПроцессы") Тогда
			Если Метаданные.БизнесПроцессы.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("ЖурналыДокументов") Тогда
			Если Метаданные.ЖурналыДокументов.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("Задачи") Тогда
			Если Метаданные.Задачи.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("ПланыСчетов") Тогда
			Если Метаданные.ПланыСчетов.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("ПланыОбмена") Тогда
			Если Метаданные.ПланыОбмена.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("ПланыВидовХарактеристик") Тогда
			Если Метаданные.ПланыВидовХарактеристик.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		ИначеЕсли ИмяВида = ВРег("ПланыВидовРасчета") Тогда
			Если Метаданные.ПланыВидовРасчета.Найти(ИмяОбъекта) <> Неопределено Тогда
				ОбъектНайден = Истина;
			КонецЕсли;
		КонецЕсли;

	КонецЕсли;

	Если Не ОбъектНайден Тогда
		ВызватьИсключение СтрШаблон(
			НСтр("ru = 'Объект метаданных ""%1"" не найден,
				 |либо для него не поддерживается получение модуля менеджера.'"), Имя);
	КонецЕсли;

	//@skip-check server-execution-safe-mode
	Модуль = Вычислить(Имя); // ВычислитьВБезопасномРежиме не требуется, т.к. проверка надежная.

	Возврат Модуль;
КонецФункции

#КонецОбласти